seeing is believing

Exploiting glibc __tzfile_read Integer Overflow To Buffer Overflow And Vsftpd

Exploiting glibc __tzfile_read Integer Overflow To Buffer Overflow And Vsftpd
Posted Dec 13, 2011
Authored by Ramon de C Valle | Site rcvalle.com

This is a write up that discusses exploiting the glibc __tzfile_read integer overflow to buffer overflow and leveraging Vsftpd.

tags | paper, overflow
MD5 | 761eafe34246bc9609dce3ba94413dea

Exploiting glibc __tzfile_read Integer Overflow To Buffer Overflow And Vsftpd

Change Mirror Download
Author: Ramon De C Valle


Exploiting glibc __tzfile_read integer overflow to buffer overflow and vsftpd

Earlier in 2009, in a blog post[1], dividead published a integer overflow to buffer overflow vulnerability in within __tzfile_read function of glibc, this issue haven’t came into my attention until, in a post to the Full-Disclosure mailing list, Kingcope[2] noted vsftpd as a potential attack vector for this issue.

This issue is a integer overflow to buffer overflow vulnerability within __tzfile_read function of glibc. The __tzfile_read function is used internally by some functions of the glibc time library to load specified timezone files.

As dividead noted in his blog post, the __tzfile_read function parses values from a specified timezone file, such as number of transition times and others, without any checking:

[...]

)
208 goto lose;
209
210 num_transitions = (size_t) decode (tzhead.tzh_timecnt);
211 num_types = (size_t) decode (tzhead.tzh_typecnt);
212 chars = (size_t) decode (tzhead.tzh_charcnt);
213 num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
214 num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
215 num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
216
217 /* For platforms with 64-bit time_t we use the new format if available.
* /

[...]

In sequence, the __tz_file_read function uses these values to allocate memory for storing structures from the specified timezone file:

[...]

233
234 goto read_again;
235 }
236
237 total_size = num_transitions * (sizeof (time_t) + 1);
238 total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
239 & ~(__alignof__ (struct ttinfo) - 1));
240 types_idx = total_size;
241 total_size += num_types * sizeof (struct ttinfo) + chars;
242 total_size = ((total_size + __alignof__ (struct leap) - 1)
243 & ~(__alignof__ (struct leap) - 1));
244 leaps_idx = total_size;
245 total_size += num_leaps * sizeof (struct leap);
246 tzspec_len = (sizeof (time_t) == 8 && trans_width == 8
247 ? st.st_size - (ftello (f)
248 + num_transitions * (8 + 1)
249 + num_types * 6
250 + chars
251 + num_leaps * 12
252 + num_isstd
253 + num_isgmt) - 1 : 0);
254
255 /* Allocate enough memory including the extra block requested by the
256 caller. */
257 transitions = (time_t *) malloc (total_size + tzspec_len + extra);
258 if (transitions == NULL)
259 goto lose;
260

[...]

As also noted by dividead in his blog post, these values can be easily manipulated to make the __tzfile_read function evaluating a value for memory allocation that results in a total size which differs from the real size of the sum of the number of structures, which are subsequently parsed and read from the specified timezone file into this buffer (i.e. transitions).

Although this seems to be a totally predictable environment for exploitation, this issue has a very limited scope due to the heap consistency checkings in glibc.

Regardless the possibility of making the __tz_file_read function allocating a chunk from fast bins (chunks of size less than 64 bytes), main arena or, eventually, a new mapped memory region, it is very difficult to guarantee a contiguity of known allocated chunks because the __tz_file_read function allocates a single chunk, which is the overflowed chunk, and it always frees this chunk upon returning.

In addition, due to the the FIFO feature of the current malloc implementation, this single chunk can be allocated from any of the various heap uncontiguous free spaces, this turns out to be very difficult to predict anything about the adjacent allocated chunk, if it is even allocated, and if so, most important, when it will be freed (and there is also the possibility of this single chunk being the wilderness chunk). This limits the predictable scope to glibc scope, more specifically within __tz_file_read function and considerably increases the difficulty of applying any known public exploitation technique to this issue.

However, one thing caught my attention. The __tzfile_read function allocates a FILE structure before allocating this single chunk and closes this structure after the chunk is overflowed but, most important, before it is freed.

[...]

179
180 /* Note the file is opened with cancellation in the I/O functions
181 disabled. */
182 f = fopen (file, "rc");
183 if (f == NULL)
184 goto ret_free_transitions;
185
186 /* Get information about the file we are actually using. */
187 if (fstat64 (fileno (f), &st) != 0)
188 {
189 fclose (f);
190 goto ret_free_transitions;
191 }
192
193 free ((void *) transitions);
194 transitions = NULL;
195
196 /* Remember the inode and device number and modification time. */
197 tzfile_dev = st.st_dev;

[...]

The single chunk (i.e. transitions) can be overflowed between the above and below listings:

[...]

422 /* Don't use an empty TZ string. */
423 if (tzspec != NULL && tzspec[0] == '\0')
424 tzspec = NULL;
425
426 fclose (f);
427
428 /* First "register" all timezone names. */
429 for (i = 0; i < num_types; ++i)

[...]

497 return;
498
499 lose:
500 fclose (f);
501 ret_free_transitions:
502 free ((void *) transitions);
503 transitions = NULL;
504 }
505

[...]

But remember the previously mentioned FIFO feature of the current malloc implementation. If we make the __tzfile_read function allocating a chunk from main arena (file structures are larger than 64 bytes), with approximately the same size of a file structure, it is very likely this single chunk will be allocated from a free uncontiguous space located before the file structure if previous allocations and frees of the approximately same size have already been made (i.e. unsorted chunks feature).

This turns out an unpredictable to a very predictable environment for exploitation, not only in glibc scope but completely within __tzfile_read function, by exploiting _IO_file_jumps of the FILE structure. Thus, making almost any application which uses glibc time library exploitable when an arbirary timezone file can be specified.

As noted by Kingcope in his post to the Full-Disclosure mailing list, vsftpd uses glibc time library and calls __tzfile_read at some point in which an arbitrary timezone file can be specified.

In vsftpd, the __tzfile_read function is reached through calls to gmtime, localtime, and tzset functions in vsf_sysutil_statbuf_get_date, vsf_sysutil_statbuf_get_numeric_date, vsf_sysutil_tzset, and vsf_sysutil_get_current_date functions. All these functions can be used to make the previous allocations and frees previously required.

To be short, the most straightforward method is through the vsf_sysutil_get_current_date function called by transfer logging functions of vsftpd. After logging in to vsftpd, we can make an arbitrary (but no so small) sequence of uploads of valid timezone files to the path expected by vsftpd followed by the specially-crafted timezone file to exploit the _IO_file_jumps of the of FILE structure.

I haven’t wrote an exploit for this issue yet, however, writing one seems fairly trivial.

[1] http://dividead.wordpress.com/2009/06/01/glibc-timezone-integer-overflow/
[2] http://lists.grok.org.uk/pipermail/full-disclosure/2011-December/084452.html


Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

July 2017

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jul 1st
    2 Files
  • 2
    Jul 2nd
    3 Files
  • 3
    Jul 3rd
    15 Files
  • 4
    Jul 4th
    4 Files
  • 5
    Jul 5th
    15 Files
  • 6
    Jul 6th
    15 Files
  • 7
    Jul 7th
    10 Files
  • 8
    Jul 8th
    2 Files
  • 9
    Jul 9th
    10 Files
  • 10
    Jul 10th
    15 Files
  • 11
    Jul 11th
    15 Files
  • 12
    Jul 12th
    19 Files
  • 13
    Jul 13th
    16 Files
  • 14
    Jul 14th
    15 Files
  • 15
    Jul 15th
    3 Files
  • 16
    Jul 16th
    2 Files
  • 17
    Jul 17th
    8 Files
  • 18
    Jul 18th
    11 Files
  • 19
    Jul 19th
    15 Files
  • 20
    Jul 20th
    15 Files
  • 21
    Jul 21st
    15 Files
  • 22
    Jul 22nd
    7 Files
  • 23
    Jul 23rd
    2 Files
  • 24
    Jul 24th
    19 Files
  • 25
    Jul 25th
    28 Files
  • 26
    Jul 26th
    2 Files
  • 27
    Jul 27th
    0 Files
  • 28
    Jul 28th
    0 Files
  • 29
    Jul 29th
    0 Files
  • 30
    Jul 30th
    0 Files
  • 31
    Jul 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2016 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close