php复杂变量的应用

php复杂变量的应用

前言

这道题主要是在做南溟师傅的学弟出的题时碰到的,后续还做了2019年De1的题中碰到过,所以想要记录下学习的历程。

题目

原题长这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
include'flag.php';
error_reporting(0);
show_source(__FILE__);
extract($_GET);
if(isset($pass) )
{
$content=trim(file_get_contents($user));
if(strcmp($pass,$content)==0 && $pass !='flag')
{
$str = $content;

eval('$a="' . $str . '";');
}
else
{
echo 'hack~~';
}

}
?>

第一次看到这个题目时,我的理解就是这里$str直接被拼接入eval所以可以直接执行代码,直接”;你的代码;$a1=”即可获取到flag.php的内容。

一些扩展

但是有些地方还是值得思索的,例如有没有什么办法能直接回显flag.php中的变量?并且我们可以再加入一个限制,比如禁止使用单引号和双引号,

1
eval('$a="' .addslashes($str) . '";');

这个点我以前也在实战中遇到过一回,所以特别记忆犹新,那个利用点是可以写配置的,然后有类似:

1
2
fwrite('\$m="'.some_filter_function($_global['m']).'""');
fwrite('\$m1="'.some_filter_function($_global['m1']).'""');

当时没想到解决方法,就找了另外的点getshell,但现在看来还是操作一下的。

关于复杂变量的理解

例如这道题给出的预期解就是${system(print_r($flag))},如何理解呢?

在此之前,我们先做个直观的实验

双引号中可以解析带$符号的变量,而像{}也会导致同样的结果,也就是说$紧挨着{可以将字符串解析为变量。并且,在括号中表达式执行的优先级是较高的,所以就有:

我们来理解下这个式子,${system(print_r($flag))},我们反着理解整个过程。

首先最内层解析$flag,

然后解析print_r($flag),

我们查到print_r实际上是有返回值的,这就好办了,system(print_r($flag))能被解析,实际上这里就是$a=print_r($flag); system($a);这样的式子,

当然报错还是会报错的。最后${}解析里面的整个表达式,最后作为变量赋值给$a

这里我们回过头来看看实战中碰到的点,我们的目标是getshell。

那么整个antsword的shell也是可以的。$m= {$_POST[1]};$m1=${@eval(${m})};,即可getshell。1=phpinfo();

总结

php一些性质还是比较有意思的,比如伪协议什么的,做题还是碰到不少的,以后多看看。