Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析

admin 2020年12月10日18:16:58评论46 views字数 3620阅读12分4秒阅读模式
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
 



漏洞背景



ptrace是linux的进程调试syscall,我们可以使用它在一个进程(tracer)中追踪调试另一个进程(tracee)。
PTRACE_TRACEME被tracee使用,作用是让自己的父进程成为自己的tracer。例如我们执行fork之后,在child中执行PTRACE_TRACEME,这样parent就成为了tracer,child成为tracee。
 



漏洞成因



我们从补丁看起:
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
这个补丁修复了两个bug,我们关心的是__task_cred(new_parent)到current_cred()的变动。
补丁之前的ptrace_link()是这样处理的:
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
这样,我们的child就可以获取new_parent的credentials。
如果一个child执行了PTRACE_TRACEME,最终会调用ptrace_link()。它的parent会成为tracer,它本身加入parent的ptraced列表,且parent的credentials会被child获取,存储于child->ptracer_cred。
一个普通权限的用户可以利用这一点创建一个privileged的ptrace关系,并用其完成提权。大致思路是,当ptracer是privileged进程时,它的tracee(也就是child),使用execve执行一个suid程序,会是正常的suid模式,也就是获得suid程序owner的权限,其EUID改变。
execve()的作用是用新的程序替换掉当前进程的image,不涉及进程创建,进程属性也大多保持不变。
当执行的程序具有SUID时,进程的euid会变为程序文件owner的uid。但有例外:
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
我们的使用情景符合第三个情况,于是execve执行的suid程序是不会set-UID的,那么tracee执行suid程序到底有没有set-UID,就靠ptrace机制自己决定。
然后ptrace的机制就是,如果tracer是priviliged,那么tracee就可以set-UID。
我们回想一下PTRACE_TRACEME的过程,当parent没有trace child的时候,它可能是privileged进程,这时我们的child使用PTRACE_TRACEME,强制parent成为自己的tracer,那么child在ptrace看来就是由一个priviliged进程所trace的,它执行suid程序也就可以实现set-UID了。
再解释个可能的疑问。既然execve执行suid程序正常情况下可以获得set-UID,那我们直接执行suid程序然后replace为我们自己的程序可以么?听起来好像可以,但execve执行成功之后永远不会return到你调用它的函数里,因为原进程已经被replace了,你无法继续往它里面注入自己的程序,换言之,suid程序的执行不受你的控制。但ptrace机制保证了你可以对tracee进行完全控制,你完全可以在tracee做了set-UID之后,replace它的程序为自己的程序。
然后还有一点,你也不能替换掉tracer进程的程序,因为当它执行suid程序时,是无法被你trace的,你也就无法借用上文所述的方法去注入你的程序。这个叫做dumpable:
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
如何使用ptrace操作tracee,使其程序被替换为我们想要的程序,这本身也是比较有技术含量的。
如图,作者先wait目标tracee的pid让其正常exit,然后从fd参数执行想要的程序(execveat(),使用syscall实现的)替换掉原程序,并detach,等待它的exit。
执行syscall的时候,它也改变了程序的argv为*arg0,然后该程序(也就是poc本身)的main会判断argv来执行不同stage。
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
注:在linux的文档中,credentials是指process identifiers,它们包括了PID信息,以及user/group identifiers等等,后者也就是UID/GID,具体分如下情况(我们通常只关心前三个):
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
其中saved set-user-ID用于保存程序执行前的effective UID,例如一个普通权限的UID 1000。这个机制对具有set-user-ID的程序起作用,它们可以drop掉自己的privileged身份(切换到saved set-user-ID),也可以重新claim权限(切到real user-ID)。
 



漏洞利用



漏洞作者 [email protected] 的利用思路相当巧妙,涉及两个ptrace和三个stage。
具体解释如下:
task A: fork()一个child, task B
task B: fork()一个child, task C
task B: execve(/some/special/suid/binary),这里是pkexec:

Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析

pkexec是具有set-UID的binary程序,它执行时是其owner也就是root的身份,但我们的A无法attach到这个privileged进程,于是我们接着就需要drop privilege,也就是前文所述的原理,这样才能被A PTRACE_ATTACH并控制。
这里pkexec指定了--user为当前用户,其execve的helper也就最终变成了dumpable的进程,可以被A所PTRACE_ATTACH。

task C: 使用PTRACE_TRACEME (建立 privileged ptrace relationship),结合3来看,我们的C在pkexec运行时,可以得到一个root身份的tracer:

Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析

task C: execve(/usr/bin/passwd),此时C的进程就是运行passwd了,这是以root身份运行的set-UID程序。
由于PTRACE_TRACEME的使用,C在execve()这里收到SIGTRAP,挂起以供其tracer追踪。

Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析

Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析

task B: drop privileges (setresuid(getuid(), getuid(), getuid())),这里poc是使用pkexec的--user选项完成了这些工作。
task B: become dumpable again (e.g. execve(/some/other/binary)),B进程的程序替换为helper,然后重新成为dumpable的程序(因为SUID程序非dumpable)。
task A: 此时A可以PTRACE_ATTACH到B进程,成为其tracer。
task A: use ptrace to take control of task B
task B: use ptrace to take control of task C
stage 1是A进程起始,直到attach到B进程之后,在B中执行stage 2。
stage 2中,B使用waitpid()去获取child pid (C),并在C执行stage 3,也就是spawn_shell(),通过setresgid()和setresuid(),把自己的uid和gid全部设为0,并执行bash,弹出root shell。
C在执行stage 3的时候,是有CAP_SETUID权限的,因为它在此之前通过其tracer的privileged身份,执行的passwd是以正常的SUID执行(passwd的owner是root),也就是说C进程成为了root身份(passwd的owner)。
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
最后,poc的测试结果如下图。
本poc使用的pkexec只可以在本地session运行,否则需要二次认证,因此无法在ssh session中使用。
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析
 



参考资料



● https://bugs.chromium.org/p/project-zero/issues/detail?id=1903
● http://man7.org/linux/man-pages/man2/ptrace.2.html
● https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6994eefb0053799d2e07cd140df6c2ea106c41ee
● http://man7.org/linux/man-pages/man7/capabilities.7.html
(点击“阅读原文”查看链接)
Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析

- End -
精彩推荐

ThinkPHP5.0.x RCE分析与利用

V8逃逸分析(escape-analysis)——N1CTF2020 Escape

house of banana

俄罗斯黑客组织使用Dropbox来存储恶意软件窃取到的数据


Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析


戳“阅读原文”查看更多内容

本文始发于微信公众号(安全客):Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2020年12月10日18:16:58
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Linux ‘PTRACE_TRACEME’提权漏洞(CVE-2019-13272)分析https://cn-sec.com/archives/199725.html

发表评论

匿名网友 填写信息