Qualys 研究团队在 polkit 的 pkexec 中发现了一个内存损坏漏洞,该 SUID 根程序默认安装在每个主要的 Linux 发行版上。这个易于利用的漏洞允许任何非特权用户通过在其默认配置中利用此漏洞来获得易受攻击主机上的完全 root 权限。
Polkit(以前称为 PolicyKit)是一个用于在类 Unix 操作系统中控制系统范围权限的组件。它为非特权进程与特权进程通信提供了一种有组织的方式。也可以使用 polkit 执行具有提升权限的命令,使用命令 pkexec 后跟要执行的命令(具有 root 权限)。
运行
变量n
初始值被设置为1,循环执行的次数为参数的个数,但是若参数个数为0时,此时变量n
仍然为1,并且后面执行的语句会将argv[n]
的值取出则造成了数组越界。
int main(int argc,char **argv)
{
printf("argc:%d\n",argc);
for(int i=0;i<argc;i++)
printf("argv[%d]:%s\n",i,argv[i]);
return 0;
}
将test.c
编译执行,发现argv[0]为执行文件所在路径。并且参数个数也是为1,不会出现为0的情况。因此在这种情况下pkexec
不会出现数组越界的情况。
#include <unistd.h>
int main()
{
char * const args[] = {NULL};
char * const environ[] = {NULL};
execve("./test",args,environ);
return 0;
}
将test2.c
编译执行,使用execve
函数启动test1
文件,发现此时的argc
为0。
那么使用execve
函数调用pkexec
文件就有可能会出现argc
为0,造成数组越界,下图为调试pkexec
时的情况,此时的argc
为0,但是n
为1,通过源码可以看到后续会读取argv[n]
的值,因此造成了数组越界。
pkexec
文件会执行validate_environment_variable (key, value)
用于检测key
所对应的环境变量是否合法。key
所对应的环境变量不合法则会采用g_printerr
函数打印信息,log_message
函数内部也是调用了g_printerr
进行信息的打印。exp
利用g_printerr
打印错误信息时特殊的执行流程进行getshell
。Linux
中CHARSET
不是设置为UTF-8
格式,则会调用iconv
,用于将文本从一种编码转化为另一种编码。iconv
之前需要通过使用iconv_open
分配转化描述符号。iconv_open
函数受到GCONV_PATH
环境变量影响GCONV_PATH
未设置,那么iconv_open
会加载系统默认的模块配置的缓存文件。/usr/lib/gconv/gconv-modules
GCONV_PATH
被设置,则会优先加载设置路径下的配置文件。gconv-modules
,该配置文件指定了编码转换的键值对,并且通过指定的so
文件执行转换。main_g_printerr.c
文件中调用了g_printerr
函数,而test3.c
则是我们稍后需要编译成.so
的文件,尝试利用g_printerr
函数执行自行编译的so
库。
//main_g_printerr.c
int main()
{
g_printerr("Hello World!\n");
return 0;
}//test3.c
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
void gconv()
{
}
void gconv_init(void *step)
{
printf("Hello test3\n");
exit(0);
}
//配置文件 gconv-modules
//将编码为ABCD转化为UTF-8,具体转化流程根据test3.so文件
module UTF-8// ABCD// test3 1
main_g_printerr.c
编译为main_g_printerr
,test3.c
编译为test3.so
,gconv-modules
为配置文件,内容如上。CHARSET
为ABCD
,因为配置文件写的是从ABCD
转化为UTF-8
,然后将环境变量GCONV_PATH
设置为当前目录。执行main_g_printerr
发现输出的是.so
文件中的Hello test3
pkexec
是具有suid
特殊权限的文件,因此执行pkexec
文件时是具有root
权限的。linux
的动态链接器会在特权程序执行的时候清楚危险的环境变量,因此使用execve
启动pkexec
时,即使设置了GCONV_PATH
也会被连接器清除。如下图所示test4
具有suid
权限,在test5
中使用execve
启动test4
,并且设置了GCONV_PATH
环境变量,但是可以看到test4
的环境变量中并没有GCONV_PATH
pkexec
中存在的数组越界漏洞,将GCONV_PATH
写入argv
与变量envp
在内存中是连续的,如下图所示,图片来自于PwnKit: Local Privilege Escalation Vulnerability Discovered in polkit’s pkexec (CVE-2021-4034)execve
启动pkexec
时,argv
是NULL
,因此argc
的值为0,但是pkexec
会默认将argc
的值赋值为1,因此argv[argc] = argv[1] = envp[0]
,因此envp
中的值会被越界读取。execve
启动pkexec
时envp[0]
的值为FileName:.
,并在当前目录下新建名为GCONV_PATH=.
的文件夹,该文件夹下新建名为FileName:.
的文件。pkexec
会取出argv[1]
(即envp[0]
)的值,接着通过g_find_program_in_path
函数获取文件路径从而构造出GCONV_PATH=.FileName:.
,接着该值会重新覆盖envp[0]
,至此GCONV_PATH
被成功写入。pkexec
使用g_printerr
打印错误信息即可。https://blog.qualys.com/vulnerabilities-threat-research/2022/01/25/pwnkit-local-privilege-escalation-vulnerability-discovered-in-polkits-pkexec-cve-2021-4034
https://bbs.pediy.com/thread-271423.htm
https://github.com/berdav/CVE-2021-4034
https://man7.org/linux/man-pages/man1/iconv.1.html
https://xz.aliyun.com/t/10870#toc-0
征集原创技术文章中,欢迎投递
投稿邮箱:[email protected]
文章类型:黑客极客技术、信息安全热点安全研究分析等安全相关
通过审核并发布能收获200-800元不等的稿酬。