CVE-2021-4034 pkexec 本地提权

2022-1-26 14:51:39 Author: wiki.ioin.in 阅读量:792 收藏

Qualys 近期公开了一个影响众多 Linux 发行版,而且利用效果极其稳定的 Polkit 漏洞 CVE-2021-4034。Qualys 在文章中完整介绍了漏洞细节,没有放出 exploit,只有演示视频。

目前网络上已经出现完整 PoC。

原文作者在 Ubuntu、Debian、Fedora 和 CentOS 的默认安装环境上均测试通过。漏洞利用难度不高,最早引入问题的 commit 来自 2009 年,影响版本范围远超去年的 sudo 漏洞。反正我自己的虚拟机和 VPS 无一幸免。

这个漏洞是本地触发,只有在获得有限权限的前提下提升至 root。请大家综合考虑自己的业务影响做好升级工作。

Polkit 是一个应用程序级别的工具集,通过定义和审核权限规则,实现不同优先级进程间的通讯:控制决策集中在统一的框架之中,决定低优先级进程是否有权访问高优先级进程。

Polkit 在系统层级进行权限控制,提供了一个低优先级进程和高优先级进程进行通讯的系统。和 sudo 等程序不同,Polkit 并没有赋予进程完全的 root 权限,而是通过一个集中的策略系统进行更精细的授权。

这个漏洞细节很有意思。


细节分析

以下内容整理自网络上的公开信息,仅供技术研究目的。本文不包含任何具体的漏洞利用代码。

漏洞出在 pkexec 命令上。

pkexec --version |       --help |       --disable-internal-agent |       [--user username] PROGRAM [ARGUMENTS...]

在 main 函数里,如果传入的命令不是绝对路径,就会在 PATH 环境变量的目录里搜索。

在 534 行的 for 循环从下标 1 开始遍历 argv[]。但 Linux 里 argv 允许只包含一个元素,就是使用 execve 并给 argv 传入 {0},此时 argc 就是 0。

这个 for 循环结束之后,变量 n 为 1。第 610 行产生了第一个越界读,而第 639 行产生了一个越界写,把 g_find_program_in_path 返回的指针尝试写回 argv[1]。

调用 execve 之后,新进程的栈如下:

argv[0]

"program"

argv[1]

"option"


argv[argc]

NULL

envp[0]

"value"

envp[1]

"PATH=name"


envp[envc]

NULL

巧合的是 argv 之后正好马上接的是 envp 的第一个元素,完全可控。只要不是 / 开头的字符串就会进入越界写的分支。如果能控制 g_find_program_in_path  返回的字符串,就可以注入任意的环境变量。

这个内存安全(memory safety)问题瞬间变成了一个逻辑漏洞。

作者传入 PATH=folder,然后在 folder 目录里放置一个可执行文件 value,那么字符串 folder/value 就会写回 envp[0]。再进一步,让这个组合的文件名里包含等号 "="。传入 PATH=name=. ,创建一个 name=. 目录,并在其中放一个可执行文件 value,最终 envp[0] 就会被篡改为 name=./value,也就是注入了一个新的环境变量进去。

回到这个命令本身,pkexec 具有 suid,在执行入口程序之前不安全的环境变量都会被过滤一遍;由于这个漏洞的存在,这个过滤措施可以直接绕过。


这个漏洞将一个内存安全的 off-by-one 问题转化成了参数注入,关键出错的代码不长,颇有 ctf 的味道。

值得一提的是 GitHub Security Labs 在去年就发过一篇 Polkit 的本地提权漏洞 CVE-2021-3560,只是利用条件有一定限制。Qualys 很有可能是看了这篇分析然后开始审计代码。

封面图来自 Unsplash 摄影师 Gabriel Heinzer

参考资料

  1. PwnKit: Local Privilege Escalation Vulnerability Discovered in polkit’s pkexec (CVE-2021-4034)
    https://blog.qualys.com/vulnerabilities-threat-research/2022/01/25/pwnkit-local-privilege-escalation-vulnerability-discovered-in-polkits-pkexec-cve-2021-4034

  2. Privilege escalation with polkit: How to get root on Linux with a seven-year-old bug
    https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/

  3. Polkit
    https://wiki.archlinux.org/title/Polkit_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)