12-%00截断(Get型)
%00截断利用的是PHP旧版本在处理文件名时的一个漏洞,可以欺骗服务器,将本不允许上传的*.php文件保存为合法的*.jpg文件,从而获得WebShell。
📝 漏洞原理:都是 null 字符惹的祸
这个漏洞的核心是ASCII码值为0的null字符(%00或0x00)。在C语言等底层语言中,这个字符被当作字符串的结束标志。
PHP的部分文件处理函数(如move_uploaded_file())底层是用C语言实现的。当它们在构造文件路径时,一旦遇到0x00,就会认为字符串到此结束,并无情地丢弃其后的所有内容。攻击者正是利用这一点,让服务器在保存文件时"断章取义"。
🔎 源码分析:漏洞是如何产生的
第十二关的源码是理解问题的关键:
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
源码中的关键点如下:
- 白名单验证 :程序会检查上传文件的后缀名(如
.jpg,.png,.gif)是否在白名单内。 - 路径可控 :文件最终保存的路径
$img_path中,$_POST['save_path']部分完全由用户通过POST请求控制。 - 拼接缺陷 :程序直接将用户可控的
$_POST['save_path']与服务器生成的文件名进行了拼接。
因此,攻击的核心思路就是:控制$_POST['save_path']参数,在其中注入null字符,从而"截断"掉后面服务器自动添加的、合法的.jpg后缀。
🛡️ 利用条件:复现漏洞的前提
要成功复现此漏洞,需要满足以下两个关键条件,这也是在实际渗透测试中判断是否存在此漏洞的重要依据:
- PHP版本低于5.3.4:该漏洞在高版本中已被修复。
-
magic_quotes_gpc 配置为 Off :若此选项开启,会转义%00这类特殊字符,导致注入失败。 - (补充)取决于底层函数实现:此漏洞并非所有PHP文件操作函数都存在,关键在于该函数是否基于C语言的字符串处理逻辑。