exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Exploiting glibc __tzfile_read Part II

Exploiting glibc __tzfile_read Part II
Posted Dec 13, 2011
Authored by Ramon de C Valle

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

tags | paper, overflow
SHA-256 | 9fa157a07080306dfb186dfc7d65fae1fe12c4ff8c7beeb94a90bd9698026603

Exploiting glibc __tzfile_read Part II

Change Mirror Download
Author: Ramon De C Valle


More on exploiting glibc __tzfile_read integer overflow to buffer overflow and vsftpd

A few hours after I posted a link to my previous blog post to the Full-Disclosure mailing list, Kingcope, in another post[1], noted a very straightforward method for acquiring arbitrary code execution through loading of a dynamic library file inside the chroot environment, wiping out all my enthusiasm in making an exploit for this issue.

However, there are some details I think are worth mentioning, since the exploitation pattern noted in my previous post can be applied to other similar vulnerabilities.

As noted in my previous post, we can turn out an unpredictable to a very predictable environment for exploitation within a limited scope, such as a single function, through features of the current malloc implementation, such as the FIFO feature (i.e. unsorted chunks), the order of memory allocations and frees within this limited scope, and a pattern of repeated actions.

The following program illustrates how we can force the reordering of the allocation of two chunks within a known limited scope (i.e. __tzfile_read):

Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static time_t *transitions = NULL;
int __use_tzfile = 1;

void
__tzfile_read()
{
register FILE *f;

__use_tzfile = 0;

f = fopen("/usr/share/zoneinfo/GMT0", "rc");
printf("f = %p\n", f);

free((void *)transitions);
transitions = NULL;

transitions = (time_t *)malloc(sizeof(FILE));
printf("transitions = %p\n", (void *)transitions);

fclose(f);

__use_tzfile = 1;
return;

lose:
fclose(f);

ret_free_transitions:
free((void *)transitions);
transitions = NULL;
}

int
main(int argc, char *argv[])
{
int i;

/* This simulates the sequence of four uploads of valid timezone files
* to the path expected by vsftpd.
*/
for (i = 0; i < 4; i++) {
/* This simulates previous memory allocations that may eventually
* happen between calls to gmtime, localtime, and tzset functions,
* initializing the main arena, and preventing consolidation.
*/
malloc(sizeof(FILE));
__tzfile_read();
}

exit(EXIT_SUCCESS);
}
When executing this program, you should see an output similar to this:

Code:
[rcvalle@localhost ~]$ gcc -Wall -Wno-unused-label unsorted.c; ./a.out
f = 0x9e4f0a0
transitions = 0x9e4f208
f = 0x9e4f2a0
transitions = 0x9e4f138
f = 0x9e4f268
transitions = 0x9e4f138
f = 0x9e4f300
transitions = 0x9e4f138
Notice we forced the reordering of the chunks allocated for the FILE structure and the transitions buffer in the main arena, through the FIFO feature, the order of memory allocations and frees within our limited scope, in this case, the __tzfile_read function, and a pattern of repeated actions. In addition, notice we also can predict the offset from one chunk to the other and control the amount of memory allocated between them (more on this later).

To be short, I replaced the FILE structure in the previous program by a simple structure containing a function pointer which is subsequently called in place of fclose function within our limited scope:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

static time_t *transitions = NULL;
int __use_tzfile = 1;

typedef struct myfuncs {
unsigned int (*mysleep)(unsigned int seconds);
/* This padding is to make this structure larger than 64 bytes, thus
* being allocated from main arena.
*/
char padding[sizeof(FILE)-sizeof(void *)];
} myfuncs_t;

void
__tzfile_read()
{
register myfuncs_t *f;

__use_tzfile = 0;

f = malloc(sizeof(myfuncs_t));
f->mysleep = &sleep;
printf("f = %p\n", f);

free((void *)transitions);
transitions = NULL;

transitions = (time_t *)malloc(sizeof(FILE));
printf("transitions = %p\n", (void *)transitions);

f->mysleep(3);
free((void *)f);

__use_tzfile = 1;
return;

lose:
free((void *)f);

ret_free_transitions:
free((void *)transitions);
transitions = NULL;
}

int
main(int argc, char *argv[])
{
int i;

/* This simulates the sequence of four uploads of valid timezone files
* to the path expected by vsftpd.
*/
for (i = 0; i < 4; i++) {
/* This simulates previous memory allocations that may eventually
* happen between calls to gmtime, localtime, and tzset functions,
* initializing the main arena, and preventing consolidation.
*/
malloc(sizeof(FILE));
__tzfile_read();
}

exit(EXIT_SUCCESS);
}
When executing this program, you should see an output similar to this:

Code:
[rcvalle@localhost ~]$ gcc -Wall -Wno-unused-label unsorted2.c; ./a.out
f = 0x82ad0a0
transitions = 0x82ad138
f = 0x82ad1d0
transitions = 0x82ad138
f = 0x82ad268
transitions = 0x82ad138
f = 0x82ad300
transitions = 0x82ad138
Notice we again forced the reordering of the chunks allocated, but now for the myfuncs structure. Therefore, if an overflow occurs inside our scope with a fopen(malloc), free, malloc, fclose(free) pattern of calls (there may be other patterns) and the data overflowed is used before the overflowed buffer is freed (i.e. fclose, myfuncs->sleep), we have a complete predictable environment for exploitation.

I added an overflow in the previous program to illustrate this:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

static time_t *transitions = NULL;
int __use_tzfile = 1;

typedef struct myfuncs {
unsigned int (*mysleep)(unsigned int seconds);
/* This padding is to make this structure larger than 64 bytes, thus
* being allocated from main arena.
*/
char padding[sizeof(FILE)-sizeof(void *)];
} myfuncs_t;

void
__tzfile_read()
{
register myfuncs_t *f;

__use_tzfile = 0;

f = malloc(sizeof(myfuncs_t));
f->mysleep = &sleep;
printf("f = %p\n", f);

free((void *)transitions);
transitions = NULL;

transitions = (time_t *)malloc(sizeof(FILE));
printf("transitions = %p\n", (void *)transitions);

memset(transitions, 'A', sizeof(FILE) * 8);

f->mysleep(3);
free((void *)f);

__use_tzfile = 1;
return;

lose:
free((void *)f);

ret_free_transitions:
free((void *)transitions);
transitions = NULL;
}

int
main(int argc, char *argv[])
{
int i;

/* This simulates the sequence of four uploads of valid timezone files
* to the path expected by vsftpd.
*/
for (i = 0; i < 4; i++) {
/* This simulates previous memory allocations that may eventually
* happen between calls to gmtime, localtime, and tzset functions,
* initializing the main arena, and preventing consolidation.
*/
malloc(sizeof(FILE));
__tzfile_read();
}

exit(EXIT_SUCCESS);
}
When executing this program, you should see the Segmentation Fault occur due to calling our overflowed function pointer:

Code:
$ gcc -Wall -Wno-unused-label unsorted3.c; ./a.out
f = 0x956d0a0
transitions = 0x956d138
f = 0x956d1d0
transitions = 0x956d138
Segmentation fault (core dumped)
In GDB:

Code:
(gdb) r
Starting program: /home/rcvalle/a.out
f = 0x804a0a0
transitions = 0x804a138
f = 0x804a1d0
transitions = 0x804a138

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
Missing separate debuginfos, use: debuginfo-install glibc-2.14-5.i686
(gdb)
Additionally, as I previously mentioned, we also can predict the offset from one chunk to the other and control the amount of memory allocated between them. This can be used to store a large amount of nop instructions or equivalent along with the shellcode, increasing considerably the chances of a successful exploitation. Also, if this memory is not used within our limited scope, the code that eventually may use this will never be reached after the overflow, thus not requiring any patching.

I hope this method of forcing the reordering of chunks allocation being useful to you.

[1] http://lists.grok.org.uk/pipermail/full-disclosure/2011-December/084717.html
Login or Register to add favorites

File Archive:

May 2024

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close