This blog post was originally published on April 27, 2010.
I wanted to share a neat little trick I discovered while playing with
gcc’s FORTIFY_SOURCE feature.
For those who don’t know, this feature attempts to prevent
exploitation of a subset of buffer overflows by inserting a set of
checks at compile-time, including stack canaries for some functions.
It’s enabled by default in many cases. In particular, when
FORTIFY_SOURCE detects an overflow, it aborts execution and
prints an error message that might look similar to the following:
*** stack smashing detected ***: ./strcpy terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x40)[0x502b30]
/lib/libc.so.6(__fortify_fail+0x0)[0x502af0]
./strcpy[0x80484d5]
[0x41414141]
======= Memory map: ========
...
Aborted
Notice that this error message contains a reference to the
application’s name, which is obtained by simply relying on
argv[0]. Assuming the application was aborted because of a
controllable stack-based buffer overflow, in some cases an attacker may
be able to continue overflowing past the vulnerable buffer, overwriting
the argv[0] pointer, causing the error message to print
arbitrary memory addresses, as in the following contrived example:
$ ./strcpy `perl -e 'print "xa0x85x04x08"x80'`
*** stack smashing detected ***: THIS IS A SECRET terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x40)[0x1f3b30]
/lib/libc.so.6(__fortify_fail+0x0)[0x1f3af0]
THIS IS A SECRET[0x80484d5]
THIS IS A SECRET[0x80485a0]
======= Memory map: ========
...
Aborted
If an attacker ever stumbles upon a setuid application with an
overflow that’s caught by FORTIFY_SOURCE, this may be used
to read the application’s address space (which may contain sensitive
information), even if code execution is mitigated. Because it relies on
the existence of another vulnerability, I wouldn’t consider this a
serious issue by any means, but it’s probably something that’s worth
fixing eventually.
Happy hacking!