Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 18 Feb 2016 20:07:30 -0500
From: Rich Felker <>
Subject: Re: Re: Address Sanitizer local root

On Thu, Feb 18, 2016 at 11:19:10PM +0000, Darren Martyn wrote:
> Hi List,
> Figured I would add this to the thread to keep it amusing.
> Here is a fully functioning local root by clobbering /etc/
> instead of /etc/shadow (which breaks things spectacularly). I am using a
> fairly messy "symlink spray"/"symlink carpet bombing" technique.
> Simply point it at a setuid-root binary compiled with asan and away it
> goes.
> Video:
> PoC Code:
> Development/Testing was done on a Debian 8.3 VM that was last updated
> last week.
> Now, I wonder - what can actually be done to mitigate against this,
> besides "don't use ASAN in production"?
> Is there something that can be done ASAN-side?
> Because due to how is parsed so, uh, forgivingly, all the
> attacker needs to control is one line in the output file. Could it check
> for symlinks before writing the log?

Fixing this whole class of bugs is trivial -- just don't process
environment vars or other invoker-controlled input when run suid. For
most things you would want to call secure_getenv (glibc) or issetugid
(BSD) to achieve this but for sanitizer libs it may make more sense to
just access the aux vector directly and check AT_SECURE and related

Of course there's a lot more state that the attacker invoking a suid
binary controlls -- resource limits, open file descriptors,
controlling ttys, signal state, etc. This also needs to be dealt with.

On a more general level, the kind of diagnostic introspection the
sanitizer libs do is just unsafe in general. Once you have a
known-compromised process state, the only thing safe to do is inducing
program termination asap. Processing complex data structures is
unsafe. Unwinding is unsafe. Function calls (especially via GOT/PLT)
and even normal system calls (on i386 where the vdso syscall pointer
is stored just after the thread stack) are unsafe. For hardening
purposes you need either an inline __builtin_trap() (and hope nobody's
catching SIGILL/SIGSEGV/SIGABRT) or ideally an inline [rt_sigprocmask,
getpid, kill] syscall sequence. Analysis of the crashing process, if
desired, should be left to an external debugger, not put in the
sanitizer libs just because it's "convenient".


Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.