SEKAI CTF 2022 writeup
第一次把 writeup 寫成 blog 文章,因為這場比賽的介面真的很可愛,身為一個 Project Sekai 玩家怎麼樣都覺得應該參與一下,又剛好遇到一個我覺得滿有趣的題目,本來覺得比賽期間不太可能解出來了,結果後來幸運解出來了,最後共解了兩題簡單題,就記錄一下,題目到現在都還在,如果有更新會再補上來。
Bottle Poem
http://bottle-poem.ctf.sekai.team 146/852 solve
這題畫面長這樣,畫面中間有一些 link,點選 link 可以連到類似這樣的網址 http://bottle-poem.ctf.sekai.team/show?id=spring.txt
拿到那個詩的 txt 檔案呈現在畫面上。
這個 /show?id=
感覺有可能可以讀檔,而直接用 id=/etc/passwd
也確實可以拿到檔案,到處看看之後可以發現
- 如果沒有這個檔案會顯示
No This Poems
id=/proc/self/cmdline
顯示 python3id=../app.py
顯示 No!!!!
到這裡可以推測他可能用類似 Flask 這樣的 python 網頁框架跑的,所以會想試著看看能不能拿到一些 Flask 可能會有的 source code,雖然用 ../app.py
會得到 No!!!!,但其實用 id=/app/app.py
是可以拿到 source 的。
1 |
|
這樣就知道為什麼剛剛 ../app.py
會出現 No!!!! 了,到這邊我的想法是覺得會不會是需要用 admin 登入呢?要用 admin 登入其實也很簡單,因為他就是單純的看 cookie 裡面的 “name” 值而已,只需要從 id=/app/config/secret.py
拿到 secret,簽出一個 session["name"] == "admin"
的 cookie 就可以了,但事情當然沒那麼簡單,拿著 admin cookie 去 /sign
頁面也只會得到這樣的頁面。
而在做這個嘗試之前,其實用個 id=/app/views/admin.html
就可以知道這是無用工了 (雖然也沒多少工),懷疑了一下這個題目到底是要我們做什麼的時候,想起了這個 cookie 的格式好像是 json 的樣子?那會不會又跟 unserialize 有關係了?果然查了一陣子看到這篇 Python Web框架会话管理:从LFR到RCE (找到的是翻譯的,但我找不到原文…如果有找到我再補上),裡面正好有講到這個 bottle 框架,翻一下 source 以後看到在他的 get_cookie 的地方有用到 pickle.loads
對這個 cookie 做事了!那答案就很明顯了,要用 unpickle RCE 吧!
最後簡單的從 source 改產出 cookie 的腳本,然後準備收 reverse shell,這題的 flag 需要執行一個在根目錄的執行檔印出來,就這樣。
1 |
|
Sekai Game Start
http://sekai-game-start.ctf.sekai.team 63/852 solve
這題就是 php 題目,直接秀 source code 給我們,總之就要傳一個 serialize 字串給他,很明顯要給的是 Sekai_Game 的序列化字串,然後在走到 Sekai_Game 的 __destruct
時 $start
要是 true 就可以拿到 flag 了。
1 |
|
這題的考點有兩個
- 怎麼傳 “sekai_game.run” 這個參數
- 繞過
__wakeup
function
第一點是個問題的原因是,在傳 GET 參數給 php 的時候,.
會自動被轉成底線,變成不管怎麼傳都沒辦法傳正確的參數進去,這個參數基本上也算是不太合法的參數,不過跳下去看這個版本 (php 7.4.5) 的 php source code 以後,可以在 main/php_variables.c 看到一段他做這些轉換的部分,然後會發現當你傳進了 [
這個字的時候,php 會覺得他是 array 然後做後續關於 array 的檢查,但是如果他找不到閉合的 ]
,他就會把這個 [
轉成 _
然後停下來,然後重點!他就什麼都不做了,包括繼續對後面的字檢查也不做了,所以當我們傳 sekai[game.run
,他最終就會轉成我們要的 sekai_game.run
了。
HexRabbit 一開始看錯版本,這個部分已經被修掉了所以一直沒找到這個解法,但也因此知道他後來有被改掉了XD
第二個問題就是要怎麼繞過 __wakeup
了,我們 Sekai_Game
的 start
要是 true,就一定不能走進 __wakeup
,這部分我查到了 PHP Bug #81151 bypass __wakeup,他的 Object 在序列化字串中用了 “C” 而不是 “O”,在 bug report 中那個人是這樣說
In my understand, “C:” means a class implements Serializable, and it don’t suport __wakeup.
我不確定他說得對不對,他也不確定,但這樣造 payload 他確實成功了 (php8 不行),於是最後的解法。
1 |
|
而如果在這裡對 Sekai_Game 多給一些參數設定又會正常執行 __wakeup
,類似這樣
1 |
|
然後如果!加上我們古時候拿來繞過 __wakeup
的方法 (CVE-2016-7124, PHP5 < 5.6.25/PHP7 < 7.0.10),又可以 bypass 了。
1 |
|
我也搞不懂了,不過反正就是這樣,這題就是奇技淫巧二連發,解不出來的時候真的滿撞牆的,因為心裡也滿清楚他一定是考什麼奇技淫巧XD,但是我又真的很想知道解法忍不了到比賽結束就到處問人,不過還好在結束前還是自己解出來了,不過看完這兩題就沒什麼心力繼續看別的題目了,耐心和耐力真的有限,希望可以慢慢進步。