what is ptrace
ptrace()
system call stands for process trace, which provides a way for debuggers such as gdb/strace to control a process (tracee). "debuggers" can be any process that sends a PTRACE_ATTACH
/PTRACE_SEIZE
, or receives a PTRACE_TRACEME
from its child.
several things to notice:
- a tracee's ptrace relationship can be found in
tracee->ptracer_cred
, which, holds tracer's credentials. in the credentials we care aboutuid/gid
, that decides what this process can do - under ptrace,
execve()
cant set-UID when executing SUID programs in current ptraced process. and yes, it allows set-UID without ptrace - but if the tracee had a privileged tracer, whose uid is stored in
tracee->ptracer_cred
, indicating that the tracee is being traced by a privileged process, the tracee can set-UID to the whatever UID the SUID program holds. its like, when you launch gdb with root, tracing an unprivileged process that executes an SUID program, it has to be allowed, right? - as for 2, the reason is when using ptrace, we can replace the tracee's SUID program with something we control, and keeps the privileged process, meaning we get root
other things you might need to read about:
the bug
now we know from note 3, the tracee->ptracer_cred
decides if the tracee's parent is privileged, if yes, we can set-UID.
actually in kernel/ptrace.c (you need to checkout the old unpatched version of course), a child is able to grab a privileged parent, and force it to become a tracer, thus get a privileged ptrace relationship
we can take advantage of this bug, but it can be challenging
the exploit
the author (jannh@google.com) wrote a beautiful PoC to exploit this bug, can be hard to understand at once. but basically its like:
forks forks
--proc_A ------> proc_B ------------> proc_C
| | | |
| wait B | |
| and attach | |
| execve stage 2 | |
| in B | |
| | |
stage 1 pkexec get privileged tracer
| | |
| | |
| unprivileged exec SUID binary,
| traced by A become privileged, SIGTRAPed
------------------------------------------------------------------
| | |
stage 2 wait C, |
| execve stage3 in C |
| |
------------------------------------------------------------------
| |
| |
stage 3 setresuid to 0, 0, 0
| |
| exeve bash as root :)
------------------------------------------------------------------
Comments
comments powered by Disqus