模板注入漏洞全匯總
- 2019 年 10 月 10 日
- 筆記
模板注入漏洞和常見的Web注入的成因類似,具有巨大的殺傷力,但因其模板引擎眾多所以利用辦法不一,故在此做一總結,文章邏輯圖如下:

1、 模板引擎介紹
1.1 模板引擎介紹
在MVC的設計模式下,一般從 Model 層中讀取數據,然後將數據傳到 View 層渲染(渲染成 HTML 文件),而 View 層一般都會用到模板引擎。
模板引擎包含了各種參數,並能夠由模板處理系統通過識別某些特定語法來替換這些參數的文檔,用來生成輸出文本(HTML網頁,電子郵件,配置文件,源程式碼等)。
模板專註於如何展現數據,而在模板之外可以專註於要展示什麼數據。模板引擎可以讓網站程式實現介面與數據分離,業務程式碼與邏輯程式碼分離,這樣提升了開發效率,良好的設計也使得程式碼重用變得更加容易。
1.2 模板引擎分類
模板引擎分為服務端和客戶端:
1) 客戶端模板引擎:主要結合js實現html,一種是常規字元串模板引擎,包括doT.js、dust.js、mustache.js;另一種是Dom模板引擎,包括vue.js、Angular.js、React.js等。
2) 服務端模板引擎:由各服務端語言生成html返回客戶端,主要包括: PHP:Smarty、Twig;
Java:Freemarker、Velocity;
Python:Jinja2、Tornado、Marko;
Ruby:Slim、ERB;
NodeJS:Jade等
1.3 模板引擎渲染原理
1)後端模板引擎
以JSP為例:

上方 <%%>內的是Java程式碼,為模板內容、<div></div> 是頁面內容
當JSP在服務端運行被編譯為Servlet Class後, <div></div> 被加引號成為字元串,輸出字元串內容,需要在服務端運行。
2)前端模板引擎

前端模板引擎依賴客戶端,在瀏覽器渲染頁面,而不依賴於服務端。
2、漏洞概述
2.1 模板注入漏洞介紹
任何一項新技術的引入同時也會帶來新的攻擊方式。除了常規的 XSS 外,注入到模板中的程式碼還有可能引發 RCE(遠程程式碼執行)。通常來說,這類問題會在部落格,CMS,wiki 中產生。雖然模板引擎本身會提供沙箱機制,但攻擊者依然有許多手段繞過它。
看一個銷售軟體的例子,業務場景中要求發送大量的郵件給客戶,並在每封郵件前插入問候語:

這段程式碼的功能是,通過Twig模板引擎可以把輸入轉換成特定的HTML文件或者email格式進行相應輸出。
很明顯我們會發現程式碼存在xss,但問題不止如此,如果我們輸入custom_email={{7*7}},$output結果為49,這種探測方式和SQL注入也極為類似,原理也都是將未過濾的數據傳給引擎解析。
2.2 攻擊手法及步驟
對於模板注入漏洞的研究可以參考SQL注入,客戶端的模板注入(CSTI)只能XSS,而服務端模板注入(SSTI)則可能造成XSS、LFI和任意程式碼執行。
漏洞發現及利用步驟分為:探測、判斷、利用(讀取、探索、攻擊)

2.2.1 探測漏洞
1、文本類型
大多數的模板都支援文本的輸入和輸出:
如:freemarker=Hello ${username},smarty=Hello {user.name}
探測方法有兩種:
1)XSS語句彈框測試;
2)使用模板語法:如reemarker=Hello${7*7},輸出為Hello 49
2、程式碼類型
用戶輸入也可以放在模板語句中,通常作為變數名稱,
如:personal_greeting=username
這種情況下,XSS的方法就無效了。但是我們可以通過破壞 template 語句,並附加註入的HTML標籤以確認漏洞,如:
personal_greeting=username<tag>
2.2.2 判斷漏洞
檢測到模板注入後,我們需要判斷具體的模板引擎。我們需要 fuzz 不同的字元,再通過返回的錯誤判斷。當模板引擎屏蔽錯誤後,該類當法就失效了,並且暴力 fuzz對攻擊自動化不友好:

根據不同模板引擎的特性,通過輸入上述payload可以快速判斷模板引擎,
這裡的綠線表示結果成功返回,紅線反之。有時同一個可執行的 payload 會在不同引擎中返回不同的結果,比方說{{7*'7'}}會在 Twig 中返回49,而在 Jinja2 中則是7777777。
2.2.3 漏洞利用
和構造sql payload類似,對於模板注入的利用程度也取決於對於各個模板特性的了解,具體需要關註:
1) Template 使用手冊,了解模板的基本語法
2) 內建方法,函數,變數,過濾器
3) 插件、擴展及沙箱機制
主要的payload集中在實現的攻擊效果在:任意對象創建,任意文件讀寫,遠程文件包含,資訊泄露以及提權。
如:Jinja2:

Marko:

3、實例講解
3.1 FreeMarker
FreeMaker 是 Java 下最受歡迎的模板引擎,在查看文檔時我們發現有兩個已發布的可接受用戶輸入並執行命令的類實現TemplateModel:
<#assigntest="freemarker.template.utility.Execute"?new()>
<#assignob="freemarker.template.utility.ObjectConstructor"?new()>
以上的payload可以在創建模板時新建一個實例,後續調用會使得命令執行:

3.2 Velocity
Velocity是另一種流行的Java模板語言,同樣發現了兩個可以利用的方法和屬性:
$ class.inspect(類/對象/串) 返回一個檢查指定類或對象的新ClassTool實例
$ class.type 返回正在檢查的實際類
可以使用$ class.type 鏈接$ class.inspect以獲取對任意對象的引用。然後使用Runtime.exec()在目標系統上執行任意shell命令:

3.3 Smarty
Smarty 是一款 PHP 的模板語言。它使用安全模式來執行不信任的模板。它只運行 PHP 白名單里的函數,因此我們不能直接調用 system()。而文檔表示可以通過 $smarty 來獲取許多環境變數後面,我們又發現了 getStreamVariable,這個方法可以用來讀取伺服器讀取+寫入許可權的任何文件:
1)任意讀取文件

2)寫文件創建後門:

3.4 Twig
Swig 和 Smarty 類似,不過我們不能用它調用靜態方法。但它提供了 _self,提供了指向 Twig_Environment 的env 屬性。Twig_Environment 其中的 setCache 方法則能改變 Twig 載入 PHP 文件的路徑。這樣就可以通過改變路徑實現 RFI:

在 getFilter 里有危險函數 call_user_func。通過傳遞傳遞參數到該函數中,可以調用任意 PHP 函數,註冊 exec 為 filter 的回調函數並調用造成命令執行:

3.5 Jade
Jade 是一款 Node.js 模板引擎,可以在Node.js等框架中使用,它有比較簡單的語法和編寫方式:

3.6 AngularJS
AngularJS是由Google編寫的MVC客戶端框架。使用Angular,通過view-source或包含'ng-app'的Burp看到的HTML頁面實際上是模板,將由Angular呈現。這意味著如果用戶輸入直接嵌入到頁面中,則應用程式可能容易受到客戶端模板注入的攻擊。即使用戶輸入是HTML編碼的並且在屬性內,也是如此。

AngularJS通過使用我們稱為指令(directives)的結構,讓瀏覽器能夠識別新的HTML標籤。AngularJS讀取自定義的HTML,並將頁面中的輸入或輸出與JavaScript變數表示的模型綁定起來。這些JavaScript變數的值可以手工設置的,或者從靜態或動態JSON資源中獲取,但只能進行XSS攻擊。
Payload如下:

4、漏洞測試及防禦
4.1 漏洞測試
對於模板注入的黑盒測試,主要是探測程式所用模板類型,尋找輸出點及攻擊特性進行攻擊;白盒測試需查看項目導入的第三方包,通過查找相關類進行跟蹤,構造攻擊向量。
4.2 防禦手段
對於不同的模板引擎,防禦方案也不相同。但做好對用戶輸入的清理/過濾,將能大大的降低此類問題帶來的安全威脅。另一個選擇是創建一個安全加固/沙箱環境,禁用或刪除潛在的危險指令。