譯者 | 劉濤
審校 | 重樓
服務器端模板注入(SSTI)漏洞是網絡應用安全中不太為人所知的一種漏洞類型。盡管這些漏洞很少見,但一旦被發現,其影響往往非常嚴重,通常會導致遠程代碼執行(RCE)。
本文旨在揭示這些問題是如何產生的,并找出它們在現實環境中經常出現的地方。
什么是服務器端模板(Server-Side Templates)
現代網絡嚴重依賴于大量的用戶信息、產品細節和各種其他類型的數據。為了以有意義的方式呈現這些信息,就需要在網頁上對它們進行有效的組織,這樣用戶才能快速找到最重要的信息;這也是用戶從精選的搞笑圖片頁面中獲得快樂的方式。
模板語言和框架引入了特殊的語法和結構,使開發人員能夠創建包含靜態內容的模板,同時提供的語法和結構允許動態內容在不需要混合后端和前端代碼的情況下呈現。
安全問題從何而來?
如果攻擊者可以發送請求,從而使服務器的模板引擎把用戶的輸入當作模板來處理,那么就會產生安全問題。一個好的安全評估在尋找這類漏洞時,需要專注考慮以下幾個方面:
管理員功能 - 允許管理員定制頁面,橫幅,或者應用程序中的其他可視元素,有時還會提供模版作為一項特色。一些開發人員甚至可能選擇允許訪問模板語言,從而打開這個漏洞。
未經過濾的輸入 - 任何可能返回給用戶或顯示在另一頁上的輸入都可能導致SSTI,具體取決于網站的功能。既然理解了模板語言的用例,那么請戴上您的開發帽,思考您會在哪些地方使用模板。
測試SSTI漏洞
如果懷疑應用程序存在SSTI漏洞,那么在應用程序中可以使用一些模板語言。測試越有針對性,效果越好。如果能夠通過偵測確定應用程序的開發語言(如Python/Java/PHP等),則可以為目標語言中常用的模板框架創建測試有效載荷。
SSTI Polyglot Payload
SSTI Polyglot有效載荷旨在跨多個框架和語言測試SSTI漏洞。在源代碼未知的情況下,它可以輔助測試。但由于此特定有效載荷很常見,且包含大量特殊字符(如${{<%[%'"}}%),所以它更可能被輸入過濾( input sanitization)攔截或被防火墻(WAFs)阻斷。
可以考慮在請求中使用有效載荷,以在目標應用程序上觸發某種錯誤消息。
GET/search?query=${{<%[%'"}}%\.
Python - Jinja2(Python的一組模板引擎)
一個簡單的用于測試應用程序是否正在處理Jinja模板的有效載荷是{{7*7}},如果應用程序正在處理該模板,則頁面上將顯示49。
為了進一步提升這個有效載荷,您可以嘗試使用下面的示例來使用Python的OS包執行date命令。
{{self.__init__.__globals__.__builtins__.__import__('os').popen('date').read()}}
在使用上述示例時,您正在使用Jinja來執行OS功能,從而執行OS命令,而這些應該包含在應用程序的類路徑中。如果應用程序的運行環境特別嚴格,但您有一個可行的SSTI POC(證明服務器端模板注入漏洞存在漏洞利用代碼),您可以考慮深入研究應用程序使用的任何其他Python包。例如,您嘗試通過SSTI訪問常用的requests包以進行進一步地利用。這類似于您可能在反序列化漏洞中看到的應用開發方式。
Jinja 過濾器旁路
您也應該知道,對于Jinja2 應用防火墻和應用程序過濾器存在繞過方法。過濾器和相關的繞過方法總是在變化,但是下面是您可能會看到的常見過濾器。
防火墻可能會攔self.__init__.__globals__.__builtins__.的某些部分。如果是這種情況,使用attr()可能會有所幫助,因為它可以直接訪問builtins(內置函數)對象。
{{ request|attr('builtins')|import('os')|popen('date')|read}}
深入研究過濾器繞過方法,您可以讓Python幫助轉換有效載荷!例如,使用format()可以在處理模板引擎時轉換有效載荷。當某些組合. or_被阻止時,這將有所幫助。
{{ request|format('%s%sbuiltins%s%s')|import('os')|popen('date')|read}}
Java模板注入
Java有更多的模板框架需要應對,可能好壞參半。基于Spring的Web應用程序非常常見,Baeldung有一個很棒的列表,網址如下:https://www.baeldung.com/spring-template-engines
ThymeLeaf(Java服務器端模板引擎)注入
這是 Java中常見的一種模板引擎類型,其利用 SSTI漏洞的方法已廣為人知。做個簡單的測試,看看是否存在模板注入漏洞,可以再次使用${7*7}這個方法,如果您在響應中看到49而不是模板,那就意味著存在問題。
這種RCE有效載荷(一種遠程代碼執行的有效載荷)有兩種變體,Spring Expression Language (SpringEL) 和 Object Graph Navigation Language (OGNL)。SpringEL比較流行,也比較現代化,但是您可能會發現 OGNL模板仍然被使用。這里是我們的示例,再次執行date命令。
SpringEL ${T(java.lang.Runtime).getRuntime().exec(‘date’)}
OGNL ${#rt = @java.lang.Runtime@getRuntime(),#rt.exec(‘date’)}
結束語
盡管本文只是一個簡單的介紹,但希望您能了解這些漏洞是如何被利用以及它們是如何產生的。這并沒有涵蓋所有可能的SSTI有效載荷和框架,但我建議您深入研究。
延伸閱讀
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server Side Template Injection/README.md
https://portswigger.net/web-security/server-side-template-injection
譯者介紹
劉濤,51CTO社區編輯,某大型央企系統上線檢測管控負責人。
原文標題:An Introduction to Server Side Template Injection Bugs,作者:David Neal