1
2
3
4
5
<?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);

xxxxx/option.php

1
2
<?php
$option='test';


这道题主要是考察配置文件写入的:
首先传入了一个GET变量option,并用addslashes进行处理
addslashes会在字符串中的单引号前面加\进行转义

1
2
3
4
<?php
$str = "abc'def";
$new_str = addslashes($str);
echo $new_str;

执行结果:

然后我们通过正则表达式将经过addslashes转义过后的字符串作为$option的值写入。
我们已经知道了这个地方可以用来写入配置信息,这个时候我们如果要写入phpinfo();,我们应该怎么做呢?
如果我们直接这样写:
?option=phpinfo();

那么这时option.php文件的内容会变成:

可以看出,我们的输入会作为一个字符串被赋值给变量option;那么我们怎么样才能将phpinfo()单独作为函数执行呢?
我们首先要想到,如果要将phpinfo作为单独的函数执行,那么就一定要逃出单引号的束缚,不然就只能作为字符串的一部分。
那么怎么逃出单引号的束缚呢?我们常用的方法有两种,第一种是就在当前行闭合单引号,然后输出phpinfo(),第二种是换行污染输出。

我们先来看第一种:

1
?option=123\';phpinfo();//

我们通过在单引号前面加\来转义函数addslashes在单引号之前加的反斜杠,执行后的option.php文件内容为:

我们可以看到,前面的123\变成了字符串,单引号未被转义。紧接着我们就执行phpinfo();,再通过//注释掉后面的那个单引号;
我们现在访问option.php就可以看到phpinfo了:

接下来再介绍第二种方法:换行污染
我们可以使用%0a来进行换行输出phpinfo(); %0a是换行的意思,相当于\n

1
?option=123';%0aphpinfo();//

执行一次后option.php:

我们可以看到,虽然换行了,不过第二行还是在字符串里面,这时候我们就需要再执行一次了,因为如果我们再执行一次的话,就会再产生一个单引号来闭合前面的单引号,让后面的phpinfo可以单独执行。
为了方便理解,我先在第一次的phpinfo前和其后加一个#符号:

然后我们再执行一次:

可以看到,新产生的字符串闭合了前面的单引号,使得phpinfo逃逸出来了。
如果连续执行两次,那么最终的option.php会是这样的:

然后我们来访问option.php:

最后用一个导图来总结一下:

最后更新: 2018年03月16日 23:37

原始链接: http://drac0nids.top/2018/03/16/challenge3/

× 请我吃糖~
打赏二维码