This is the mail archive of the
mailing list for the glibc project.
Fwd: [PATCH] Don't allow attackers to inject arbitrary data into stack through LD_DEBUG
- From: Alex <alexinbeijing at gmail dot com>
- To: libc-alpha at sourceware dot org
- Date: Mon, 10 Aug 2015 09:03:33 +0200
- Subject: Fwd: [PATCH] Don't allow attackers to inject arbitrary data into stack through LD_DEBUG
- Authentication-results: sourceware.org; auth=none
- References: <1439153945-22973-1-git-send-email-alexinbeijing at gmail dot com> <20150809224358 dot GJ14639 at brightrain dot aerifal dot cx> <CACsECNe8LPA+EpOZ3+T67x6+U2+VzQ=w66dO=vOUbhzVH0Qh_g at mail dot gmail dot com>
On Mon, Aug 10, 2015 at 12:43 AM, Rich Felker <email@example.com> wrote:
> On Sun, Aug 09, 2015 at 10:59:05PM +0200, Alex Dowad wrote:
>> C programs which use uninitialized stack variables can be exploited if an attacker
>> can control the contents of memory where the buggy function's stack frame lands.
>> If the buggy function is called very early in the program's execution, that memory
>> might still hold values written by ld.so, so manipulation of ld.so is one way to
>> carry out such an exploit.
>> But how can an unprivileged user, running a set-UID program, cause ld.so to write
>> arbitrary data onto the stack? One way is to assign it to LD_DEBUG. When printing the
>> resulting warning message, ld.so uses alloca to create a buffer on the stack, and
>> copies the entire contents of LD_DEBUG into it (even if it is dozens of kilobytes long).
>> Of course, people shouldn't write programs which use uninitialized variables, but it
>> is easy enough to plug this hole if they do -- zero out the buffer after printing the
>> warning message. Call it the "pants and suspenders" approach.
>> Dear GLibc devs,
>> Does this look like something you might be interested in merging? I've never contributed
>> before, and haven't filled in any copyright attribution papers, but am happy to do so
>> if necessary.
>> I discovered this issue while playing through a hacking "wargame" where players must
>> develop exploits against programs with deliberately planted security vulnerabilities.
>> It helped me "beat" the game by achieving a privilege escalation.
>> Alex Dowad
>> elf/rtld.c | 2 ++
>> 1 file changed, 2 insertions(+)
>> diff --git a/elf/rtld.c b/elf/rtld.c
>> index 6dcbabc..ee194a6 100644
>> --- a/elf/rtld.c
>> +++ b/elf/rtld.c
>> @@ -2408,6 +2408,8 @@ process_dl_debug (const char *dl_debug)
>> char *copy = strndupa (dl_debug, len);
>> _dl_error_printf ("\
>> warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy);
>> + /* Don't let an attacker inject arbitrary data into the stack area */
>> + __builtin_memset(copy, 0, len);
>> dl_debug += len;
> This memset will be optimized out by any decent compiler. Some
> mechanism to prevent that is needed.
> BTW are you sure you haven't uncovered a much more serious bug?
> Unbounded alloca allows the clobbering of arbitrary memory. While it's
> not entirely unbounded, the environment/argv size limit was removed on
> modern Linux, so it's quite possible to have multi-MB or even GB
> strings there. It's possible/likely that we got lucky and get an
> unconditional crash at a point where there's only one thread and no
> signal handlers, but I still think this should be checked and the
> bogus alloca removed.
Hmm. I can't see any reason why this code needs to copy the string at
all. It seems like it should be able to just print it from where it
originally resides in the env var array. Is there something I'm
missing? (CC'ing U. Drepper here since he originally wrote this