- 来源:Root-Me
- 题型:Web-Server
- 题目:PHP preg_replace()
- 分数:30 Points
挑战的提示就是利用 PHP 的 preg_replace() 函数读取 flag.php 文件的源码。
关于 preg_replace() 函数的语法定义,可以参考 这里 :
简单来说,这是正则替换函数,语法如下:
/*
*【函数定义】
* 搜索 $subject 中匹配 $pattern 的部分, 以 $replacement 进行替换
*/
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
/*
*【参数说明】
* $pattern: 要搜索的模式,可以是字符串或一个字符串数组。
* $replacement: 用于替换的字符串或字符串数组。
* $subject: 要搜索替换的目标字符串或字符串数组。
* $limit: 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。 默认是-1(无限制)。
* $count: 可选,为替换执行的次数。
*
*【返回值】
* 如果 $subject 是一个数组, preg_replace() 返回一个数组, 其他情况下返回一个字符串。
* 如果匹配被查找到,替换后的 $subject 被返回,其他情况下 返回没有改变的 $subject。
* 如果发生错误,返回 NULL。
*/
在本题中,用到的只有前 3 个参数 $pattern 、$replacement 、$subject ,最后的两个可选参数可无视掉。
开启挑战页面后,有三个输入框,每个输入框对应的参数如下:
search=>$patternreplace=>$replacementcontent=>$subject

尝试输入正常的参数,发现页面输出了替换后的字符串,但是会对特殊字符做过滤,说明函数的输出不是利用点。

其实在正则表达式中是有多种模式的,如:
/i模式:不区分大小写/g模式:全局匹配/m模式:多行匹配/e模式:将替换串中的内容当作代码来执行- ……
其中 /e 模式是 PHP 语言特有的,这也是这题的解题关键。
关于 preg_replace() 函数漏洞的利用,可以参考 这里。
简而言之,要触发 preg_replace() 漏洞有两个前置条件:
- 第一个参数
$pattern需要/e模式,使得第二个参数replacement在替换前可以作为命令代码执行 - 第一个参数
$pattern必能能够匹配到第三个参数subject(否则preg_replace()函数会返回subject而不会执行replacement命令)
例如构造这样的参数就不会执行 phpinfo() 命令(因为 /test/e 不匹配 just exp ):
preg_replace('/test/e', 'phpinfo()', 'just exp');

而构造这样的参数就可以执行 phpinfo() 命令(因为 /test/e 匹配 just test ):
preg_replace('/test/e', 'phpinfo()', 'just test');

那么要读取 flag.php 文件,只需要把 phpinfo() 命令改成 file_get_contents("flag.php") 即可。
file_get_contents是 PHP 读取文件内容的函数。
亦即可以构造 payload 为:
search=>/test/ereplace=>file_get_contents("flag.php")content=>just test
成功得到密码,完成挑战。

答案下载
flag 下载后的 flagzip 的文件需要手动更改后缀为
*.zip,然后解压即可(为了避免直接刷答案)