Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<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

Your e-mail address:

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

Powered by Openwall GNU/*/Linux - Powered by OpenVZ