CVE-2019-11043漏洞分析与复现
漏洞描述
该漏洞需要在nginx.conf中进行特定配置才能触发。具体配置如下:
location ~ [^/]\.php(/|$) {
...
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php:9000;
...
}
攻击者可以使用换行符(%0a)来破坏fastcgi_split_path_info
指令中的Regexp。Regexp被损坏导致PATH_INFO为空,从而触发该漏洞。
漏洞类型:远程代码执行漏洞
危险等级:高危
利用条件:nginx配置了fastcgi_split_path_info
受影响系统:PHP 5.6-7.x,Nginx>=0.7.31
漏洞复现
使用某个大佬的 docker 环境进行复现:
PHP-FPM 远程代码执行漏洞(CVE-2019-11043)
https://github.com/vulhub/vulhub/blob/master/php/CVE-2019-11043/README.zh-cn.md
准备工作:安装 docker、golang 环境
在kali中使用如下命令安装docker和golang:
sudo apt-get install docker docker-compose
sudo apt install golang
![](https://img2020.cnblogs.com/blog/1939770/202105/1939770-20210506164111806-1349734928.png)
![](https://img2020.cnblogs.com/blog/1939770/202105/1939770-20210506164153080-1541878856.png)
搭建漏洞环境
git clone https://github.com/vulhub/vulhub.git
cd vulhub/php/CVE-2019-11043 && docker-compose up -d
![](https://img2020.cnblogs.com/blog/1939770/202105/1939770-20210506164826309-1637457839.png)
![](https://img2020.cnblogs.com/blog/1939770/202105/1939770-20210506165539259-1375063543.png)
安装漏洞利用工具
git clone https://github.com/neex/phuip-fpizdam.git
cd phuip-fpizdam
go get -v && go build
![](https://img2020.cnblogs.com/blog/1939770/202105/1939770-20210506215625597-1324971807.png)
![](https://img2020.cnblogs.com/blog/1939770/202105/1939770-20210506220112164-1575967293.png)
漏洞利用
在phuip-fpizdam目录下执行 go run . "http://127.0.0.1:8080/index.php"后成功显示漏洞利用成功。
在浏览器进行了如下请求,成功复现,可以执行系统命令,id可以替换为其他OS命令。
![](https://img2020.cnblogs.com/blog/1939770/202105/1939770-20210506220211623-241174836.png)
![](https://img2020.cnblogs.com/blog/1939770/202105/1939770-20210506220227175-212032938.png)
漏洞分析
有漏洞信息可知漏洞是由于path_info 的地址可控导致的,我们可以看到,当path_info 被%0a截断时,path_info 将被置为空,回到代码中我就发现问题所在了。
如下漏洞代码
在代码的1134行我们发现了可控的 path_info 的指针env_path_info
其中
env_path_info 就是变量path_info 的地址,path_info 为0则plien 为0。
slen 变量来自于请求后url的长度 int ptlen = strlen(pt); int slen = len - ptlen;
由于apache_was_here
这个变量在前面被设为了0,因此path_info的赋值语句实际上就是:
path_info = env_path_info ? env_path_info + pilen - slen : NULL;
env_path_info是从Fast CGI的PATH_INFO取过来的,而由于代入了%0a
,在采取fastcgi_split_path_info ^(.+?\.php)(/.*)$;
这样的Nginx配置项的情况下,fastcgi_split_path_info无法正确识别现
在的url,因此会Path Info置空,所以env_path_info在进行取值时,同样会取到空值,这也正是漏洞原因所在。