php-FPM 基于fastcgi协议的rce漏洞复现 CVE-2019-11043
文章目录参考文章参考文章PHP-FPM Fastcgi 未授权访问漏洞PHP-FPM Fastcgi 未授权访问漏洞
1. 基础知识
1.1 fastcgi是什么
是一个协议,类似于http协议。fastcgi是一种web服务器与某种语言进行数据交换
的规则,而http协议是浏览器与web容器进行数据交换的规则。
1.2 PHP-FPM是什么
PHP-FPM就是一个实现了fastcgi协议的实体程序,全名是Fast-cij process manager,可以利用PHP-FPM可以接收web容器发过来的符合fastcgi协议格式的数据
,然后执行相应的php文件,然后将执行结果返回web容器,web容器返回给客户端。
举个例子,用户访问http://127.0.0.1/index.php?a=1&b=2,如果web目录是/var/www/html,那么Nginx会将这个请求变成如下key-value对:
{
'GATEWAY_INTERFACE': 'FastCGI/1.0',
'REQUEST_METHOD': 'GET',
'SCRIPT_FILENAME': '/var/www/html/index.php',
'SCRIPT_NAME': '/index.php',
'QUERY_STRING': '?a=1&b=2',
'REQUEST_URI': '/index.php?a=1&b=2',
'DOCUMENT_ROOT': '/var/www/html',
'SERVER_SOFTWARE': 'php/fcgiclient',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '12345',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'SERVER_NAME': "localhost",
'SERVER_PROTOCOL': 'HTTP/1.1'
}
这个数组其实就是PHP中$_SERVER
数组的一部分,也就是PHP里的环境变量
,也可以理解成php.ini文件中的部分配置,通过这个请求包而执行的php文件所使用的具体配置以请求包中定义的配置为准。
例如,假如我们可以控制这个请求包中的内容,我们可以在请求包中加上'PHP_ADMIN_VALUE': 'allow_url_include = On'
,那么此次请求的文件中就可以使用远程文件包含
。不过disable_functions
不能被配置。
PHP-FPM拿到fastcgi的数据包后,进行解析,得到上述这些环境变量。然后,执行SCRIPT_FILENAME
的值指向的PHP文件,也就是/var/www/html/index.php
,这个php文件必须在服务器内
才行。
PHP-FPM默认监听9000端口,如果这个端口可以被我们直接访问到,则我们可以自己构造fastcgi协议,和fpm进行通信。
1.3 漏洞利用原理
利用条件:
- 知道某个php文件在服务器上的绝对路径
- 可以访问PHP-FPM的9000端口
在我们可以访问到PHP-FPM的9000端口的时候我们就可以构造恶意的fastcgi格式的数据
与PHP-FPM进行通信并进行rce。
数据举例如下:
{
'GATEWAY_INTERFACE': 'FastCGI/1.0',
'REQUEST_METHOD': 'GET',
'SCRIPT_FILENAME': '/var/www/html/index.php',
'SCRIPT_NAME': '/index.php',
'QUERY_STRING': '?a=1&b=2',
'REQUEST_URI': '/index.php?a=1&b=2',
'DOCUMENT_ROOT': '/var/www/html',
'SERVER_SOFTWARE': 'php/fcgiclient',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '12345',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'SERVER_NAME': "localhost",
'SERVER_PROTOCOL': 'HTTP/1.1'
'PHP_VALUE': 'auto_prepend_file = php://input',
'PHP_ADMIN_VALUE': 'allow_url_include = On'
}
这个请求是访问index.php,且它在服务器上的绝对路径是/var/www/html/index.php,必须知道某个文件的绝对路径才能进行漏洞利用。
auto_prepend_file
是告诉PHP,在执行目标文件之前,先包含auto_prepend_file中指定的文件;auto_append_file
是告诉PHP,在执行完成目标文件后,包含auto_append_file指向的文件。
那么就有趣了,假设我们设置auto_prepend_file为php://input
,然后通过添加’PHP_ADMIN_VALUE’: 'allow_url_include = On’在fastcgi数据中来开启开启allow_url_include
。此时,index.php在加载前会先加载我们放在post请求Body中的代码,从而达到rce。
下面是php安装后默认含有的php文件:
漏洞利用结果:
补充:Nginx(IIS7)文件解析漏洞产生原因
Nginx和IIS7曾经出现过一个PHP相关的解析漏洞(测试环境https://github.com/phith0n/vulhub/tree/master/nginx_parsing_vulnerability),该漏洞现象是,在用户访问http://127.0.0.1/favicon.ico/.php时,访问到的文件是favicon.ico,但却按照.php后缀解析了。
用户请求http://127.0.0.1/favicon.ico/.php,nginx将会发送如下环境变量到fpm里:
{
...
'SCRIPT_FILENAME': '/var/www/html/favicon.ico/.php',
'SCRIPT_NAME': '/favicon.ico/.php',
'REQUEST_URI': '/favicon.ico/.php',
'DOCUMENT_ROOT': '/var/www/html',
...
}
正常来说,SCRIPT_FILENAME
的值是一个不存在的文件/var/www/html/favicon.ico/.php
,是PHP设置中的一个选项fix_pathinfo
导致了这个漏洞。PHP为了支持Path Info模式而创造了fix_pathinfo,在这个选项被打开的情况下,fpm会判断SCRIPT_FILENAME
是否存在,如果不存在则去掉最后一个/及以后的所有内容,再次判断文件是否存在,往次循环,直到文件存在。
所以,第一次fpm发现/var/www/html/favicon.ico/.php
不存在,则去掉/.php
,再判断/var/www/html/favicon.ico
是否存在。显然这个文件是存在的,于是被作为PHP文件执行,导致解析漏洞。
防御方案
1.在Nginx端使用fastcgi_split_path_info将path info信息去除后,用tryfiles判断文件是否存在;
2.借助PHP-FPM的security.limit_extensions配置项,避免其他后缀文件被解析。
2. 漏洞利用
在msf中search fpm:
填入各种参数:
执行run进行利用:
对直接暴露的9000端口进行攻击:
python3 fpm_exp.py 192.168.171.138/usr/local/lib/php/PEAR.php -c "<?php echo `ls`?>"
参考文章
PHP-FPM Fastcgi 未授权访问漏洞
PHP-FPM Fastcgi 未授权访问漏洞
Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)