數信杯南部賽區 tornado

-3發表於2024-10-13

是道WEB0解題在賽中時感覺快做出來了(其實沒有),於是賽後重新嘗試了一下,終於給搞出來了

進去是個普通頁面 沒有能ssti的點,但是透過原始碼發現了merge 就基本確定是考原型鏈汙染

需要本地搭建除錯

一開始根據原始碼

我想的是直接汙染靜態目錄 然後將靜態目錄改到根目錄下 這樣就能直接訪問到/flag

但是這裡的這個static_path是被用於初始化的,也就是隻在程式啟動時使用過一次,然後就會在某一個例項的屬性裡記載static_path的值,後面每次訪問靜態目錄時讀取的都是某個例項的屬性而不是static_path 所以這裡汙染static_path是沒用的

那我們的目的就很明確了 只要找到static_path賦給了哪些屬性,並且這個屬性確實是每次訪問靜態目錄時程式查詢的屬性就行了

透過查詢文件知道處理靜態路由主要是由StaticFileHandler這個處理程式來完成的

後面就是檢視原始碼跟蹤,最後會發現是在p.__init__.__globals__['app'].wildcard_router.rules[0].target_kwargs['path']裡

那我們只要修改p.__init__.__globals__['app'].wildcard_router.rules[0].target_kwargs['path']='/',然後再訪問http://ip:5000/static/flag就能獲得根目錄下的flag,不過我也不確定flag是不是在/flag

但是實際在payload的時候會有問題,原因就是在這個rules[0],因為這個rules是個物件陣列,如圖

裡面有四個物件,每個物件裡都有一個matcher屬性,matcher屬性也是一個物件,並且我們不能更改這個物件 否則會報錯

而我們如果payload用這樣

他就會覆蓋掉第0索引的物件,從而導致識別不到matcher這個物件而報錯,但是我們也不能在json裡新增matcher物件,因為物件沒法用字串表示

所以這個方法就不行了,只能另求他路

在剛剛除錯的時候,我發現了tornado似乎會對第一次render過的檔案進行快取

比如這道題他render了這個檔案

但是當我去更改這個檔案的時候是沒有任何變化的

所以我產生了一個想法 會不會有一個例項的屬性記載了這個檔案的內容來當作快取 例如在某一個例項裡,有一個屬性是{{handler.application.settings}},於是我每次去訪問這個檔案的時候他都會從屬性裡去讀取而不是讀取檔案,那我就可以更改這個屬性以從{{handler.application.settings}}更改為{{sstirce語句}}來觸發ssti漏洞

查閱文件發現關於快取是有一個叫_template_loaders來處理的

那我們就去這個_template_loaders裡看看

有個對應的路徑 感覺很符合我們的猜想 繼續跟

進到templates的static/index.html裡看看

發現了不得了的東西,直接有一個code變數 裡面還儲存著python程式碼

先扔給gpt問一下,說就是回顯handler.application.settings的意思 這不就是在處理我們index.html內容{{handler.application.settings}}的程式碼嗎

於是我嘗試更改了這個程式碼,但是沒有任何變化,應該也只是個用來初始化的,看到下面還有個變數compiled,意思就是編譯完的

那流程猜測一下就是先識別index.html裡的內容,並且給出對應的控制html內容的程式碼賦值給code,然後再對code進行編譯,將物件放在compiled裡

實際我們的原始碼也是這樣寫的

首次訪問檔案時,先創造對應的code,然後再用compile函式編譯,之後每次訪問這個檔案時都會執行這個編譯後的函式以達到快取的目的

好的那問題又來了

這個compiled屬性是個物件啊,又沒辦法用json來表示物件,只能表示字串,那咋辦呢

搞到這步已經半夜了,想了半天 還是先去睡個覺 隔天還有早八

上課的時候想著還是再看看原始碼 有啥利用點

一回宿舍就開始繼續看程式碼 最後在執行的部分發現了利用點

在這一步我原以為只是執行編譯後的物件,結果點進去看了一下才發現

exec_in這個函式 還會判斷你的code是不是字串,如果是編譯好的物件 那當然直接執行了,但如果是字串 他還會幫你再編譯一次,然後還會送到exec裡執行

所以我們的compiled是可以直接傳字串給他的

那我們就可以構造payload 注意繞過黑名單

之後訪問一下htpp://ip:5000/ 讓他載入一下快取程式碼

相關文章