Vulnerability Development mailing list archives

[Vuln-dev Challenge] Challenge #2


From: "D." <dugely () yahoo com>
Date: Sat, 24 May 2003 15:03:25 -0700 (PDT)

Hello vuln-dev!

As far as I can tell, most people have exploited
vulndev2.c by exploiting printf()'s got tables.
However, the way I did it was by overwriting the FILE
* and pointing it to our own specially crafted FILE
structure somewhere in memory. From there, when glibc
tries to fclose() f1 it uses the function pointer
_IO_file_jumps in the FILE structure to jump to a jump
table (which we've also placed in memory), which jumps
to our shell code.

You can see my exploit code in a previous posting, or
visit:

http://www.hcsw.org/sploits/vulndev2sploit.c

A more thourough explanation:


       /* log input */
       if ( (f1 = fopen("db.log", "a+")) == NULL)
               return 1;
       fprintf(f1, ";;%s;;", argv[2]);
       fclose(f1);

We put the memory location of where our specially
crafted FILE struct will be into the log file from
arg2.




       strcpy(buf, argv[1]);

This call does most of the work. 4 things of note are
put into memory because of it:

* A new value for bfp pointing 2 bytes before the f1
variable.
* A specially crafted FILE struct
* A jump table
* Our shellcode





       /* read log */
       if ( (f1 = fopen("db.log", "r")) == NULL)
               return 1;
       if (fgets(bfp, BFSIZE, f1) == NULL)
               return 1;

Here the program reads in data from the log file. When
fgets() writes the data to bfp, it actually overwrites
the f1 variable because we changed where f1 is
pointing in the previous step. (We point bfp to 2
bytes before f1 because the logfile entry will start
with 2 semicolons)




       fclose(f1);

The system tries to fclose() f1 which is now pointing
to our FILE struct. It follows the _IO_file_jumps,
selects one of our entries in our jump table and jumps
to it. Remember all of our entries in our jump table
point to our shellcode.




Some notes:

* We could also have pointed bfp to the actual
location in memory of where the FILE struct for fp was
closing and overwrote that, just leaving f1 pointing
to where it originally pointed. Both would have
worked.

* Originally I thought this exploit was going to be
trivial. I thought we could simply smash the stack on
the strcpy() call and overwrite main's
ret. However, this function only returns in a few
instances: not in the default case. Usually it exits
using exit() which, of course, ignores any ret calls.
A race condition might exist to exploit this however.
Consider this:

The application opens up the log file for writing and
writes its stuff. The application strcpy()s your arg1
into buf. You overwrite main()'s return code to point
at some shellcode. Now, if you're extrememly quick,
make the file non-readble in some way (deleting it,
changing perms, etc): fopen() will return NULL, and
main() will return. 0wn3d:

       if ( (f1 = fopen("db.log", "r")) == NULL)
               return 1;

It would probably be easiest to exploit this on a
lagged system accessing its filesystems over a high
latency connection like, say, NFS.

* A number of people have also suggested a symlink
attack.

* A number of people have exploited this using
printf()'s got tables.




Conclusion:

This was a very well thought out challenge: There are
a number of ways to exploit this code, and I trust it
will start some good discussion on vuln-dev.

I must disagree with "anon" in this one:

btw. the first challenge was better than this (even
if it was already well documented aswell..)

This challenge was far more interesting than the
previous. I hope vuln-dev challenges grow into a
vuln-dev tradition!



Shouts that I forgot in the .c:

madness for forwarding me the vuln-dev message
theclone, rt, magma
syke
GOBBLES for reminding us how painfully necessary
coherency is...




Doug Hoyte
Hypervivid Solutions, Inc
HardCore SoftWare
fractal@efnet

__________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo.
http://search.yahoo.com


Current thread: