CVE-2021-4034分析

    渗透测试 lz520520 2年前 (2022-03-19) 962次浏览

    漏洞介绍

    pkexec本身是用来授权用户以其他身份执行程序,他具备suid属性,但由于常规功能下不支持直接执行命令,无法利用于suid提权。

    pkexec是polkit (默认安装的系统服务)这个套件的程序。

    CVE-2021-3560 利用的dbus-send,这次是 CVE-2021-4034 利用的 pkexec,上次影响的<=0.113版本,这次影响全部版本。

    漏洞影响

    Ubuntu、Debian、Fedora 和 CentOS 等默认安装pkexec,均受影响

    安全版本

    暂时无吧

    pkexec --version查看版本

    漏洞分析

    https://github.com/wingo/polkit/blob/master/src/programs/pkexec.c

    简单来讲,就是越界读写,导致不安全的环境变量写入,这种越界写入允许我们重新引入一个 将“不安全”环境变量(例如 LD_PRELOAD)放入 pkexec 的 环境; 如果是正常设置环境变量,这些“不安全”变量通常会被删除(通过 ld.so)

    如GCONV_PATH就是不安全的环境变量,因为他会导致任意so执行。同时pkexec是一个默认具有suid属性的程序,如果能让其执行命令,那么就能导致suid提权了。

    所以利用中允许我们绕过过滤写入GCONV_PATH,然后设置gconv-modules文件,触发字符集转换,调用iconv_open加载对应字符集的so文件。

    如下是pkexec的部分代码,问题在于如果用execve调用pkexec时,如果args[] = {NULL},传入到pkexec时,argc=0,但argv[]={NULL},这个时候argv会占用一个char字符。

    534行:for循环argc=0,所以不会进入循环,但n已经设置成1

    610行:argv[1]赋值给path

    execve调用新进程的堆栈如下,argv和envp是连续的,这就会导致argv[1]=envp[0]

    如果按照上面的代码逻辑,如果传入的命令不是绝对路径,就会在 PATH 环境变量的目录里搜索,在赋值回argv

    argv[0]"program"
    argv[1]"option"
    argv[argc]NULL
    envp[0]"value"
    envp[1]"PATH=name"
    envp[envc]NULL

    比如我调用execve时,将环境变量设置成

    610行:path = 'pwnkit.so:.'

    632行:s = 'GCONV_PATH=./pwnkit.so:.'

    这里说明下,因为PATH=xxx,设置一个新的搜索目录,我只需要创建一个名为'GCONV_PATH=.'的目录,并在该目录下创建任意一个叫'pwnkit.so:.'的程序即可通过g_find_program_in_path(path)搜索到该文件

    639行:argv[1] = envp[0] = 'GCONV_PATH=./pwnkit.so:.'

    到此为止,我们就顺利的将GCONV_PATH写入到环境变量中绕过过滤了。注意这里要的是:后面的.,用于加载当前目录下的gconv-modules,前面pwnkit.so叫啥都行

    接下来的工作就是怎么触发iconv_open调用,以及iconv_open的利用链构造

    在pkexec调用g_printerr打印错误日志时,如果CHARSET设置成非UTF-8的其他字符集(CHARSET不是敏感变量,不会被过滤),就会触发iconv_open调用

    来看一下iconv_open函数的执行过程:

    1. iconv_open函数首先会找到系统提供的gconv-modules文件,这个文件中包含了各个字符集的相关信息存储的路径,每个字符集的相关信息存储在一个.so文件中,即gconv-modules文件提供了各个字符集的.so文件所在位置。
    2. 然后再根据gconv-modules文件的指示去链接参数对应的.so文件。
    3. 之后会调用.so文件中的gconv()与gonv_init()函数。
    4. 然后就是一些与本漏洞利用无关的步骤。

    linux系统提供了一个环境变量:GCONV_PATH,该环境变量能够使glibc使用用户自定义的gconv-modules文件,因此,如果指定了GCONV_PATH的值,iconv_open函数的执行过程会如下:

    1. iconv_open函数依照GCONV_PATH找到gconv-modules文件。
    2. 根据gconv-modules文件的指示找到参数对应的.so文件。
    3. 调用.so文件中的gconv()和gonv_init()函数。
    4. 一些其他步骤。

    上面这个技巧其实也在php disable function bypass里用过

    至于怎么触发错误日志呢,比如pkexec里的validate_environment_variable ,这个函数会校验SHELL或XAUTHORITY环境变量是否有效,如果校验错误,就会调用g_printerr,进而触发iconv_open的调用。

    CVE-2021-4034分析

    举例

    [

    ](https://blog.csdn.net/qq_42303523/article/details/117911859)

    根据上面分析,就需要四个文件

    主程序:构造环境变量,通过execve调用pkexec

    恶意so文件:包含gconv_init和gconv两个函数,用于执行任意恶意代码

    gconv-modules:设置需要加载的so文件

    中间目录:'GCONV_PATH=./pwnkit.so:.'

    主程序如下

    so如下,这里setuid等等,是为了linux高版本保证Effective UID和Real UID一致。

    Makefile

    其他环境变量是否也能利用,就需要进一步分析了,下面是不安全的环境变量

    补充

    https://gitlab.freedesktop.org/polkit/polkit/-/blob/0.115/src/programs/pkexec.c

    0.114+的版本中,在main函数里面多加了一句setenv,这个setenv,如果GIO_USE_VFS不存在,会在堆里重新申请内存,并把环境变量从栈迁移堆,导致无法构造越界读写。所以调用pkexec时多添加一个环境变量GIO_USE_VFS即可。

    CVE-2021-4034分析

    漏洞利用

    查看pkexec版本

    先尝试上传编译好的

    执行会获取到一个/bin/sh的交互程序

    CVE-2021-4034分析

    如果编译的无法执行,可以上传源码make,注意这里拷贝/usr/bin/true,还可能是/bin/true,根据情况改动

    CVE-2021-4034分析

    生成文件如下

    CVE-2021-4034分析

    如果执行不成功可以检查下pkexec的suid属性

    报错

    修复建议

    缓解措施,因为最终利用的是suid提权,所以只要去掉suid即可

    chmod 0755 /usr/bin/pkexec

    参考链接

    分析 https://mp.weixin.qq.com/s/3rnkcRfX_BxzlVzp0stQRw

    详细原理 https://blog.qualys.com/vulnerabilities-threat-research/2022/01/25/pwnkit-local-privilege-escalation-vulnerability-discovered-in-polkits-pkexec-cve-2021-4034

    利用 https://haxx.in/files/blasty-vs-pkexec.c

    利用 https://github.com/berdav/CVE-2021-4034

    https://mp.weixin.qq.com/s/bM20T1b39J5MHS14sdLikg

    https://xz.aliyun.com/t/10870

    其他注意事项

    [

    ](https://github.com/berdav/CVE-2021-4034)


    Security , 版权所有丨如未注明 , 均为原创丨
    转载请注明原文链接:CVE-2021-4034分析
    喜欢 (3)