模板引擎注射:針對現代web應用的新型命令執行

wyzsk發表於2020-08-19
作者: 小飛 · 2015/08/13 13:10

原文連結 https://www.blackhat.com/docs/us-15/materials/us-15-Kettle-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-wp.pdf

0x00 科普


要討論模板引擎的攻擊,先來了解下什麼是模板引擎

模板引擎(這裡特指用於Web開發的模板引擎)是為了使使用者介面與業務資料(內容)分離而產生的,它可以生成特定格式的文件,用於網站的模板引擎就會生成一個標準的HTML文件。(百度百科) 說白了,就是使得後端資料轉換成前端html以及樣式的中間應用件。

0x01 摘要


模板引擎(Template engines)在現代web應用被廣泛使用,它們被用來動態地顯示資料。然而,不安全地將使用者輸入嵌入到模板中,會導致一系列針對伺服器的注入攻擊。然而,這種漏洞很容易被誤當做Xss對待。然而,針對模板的注入其實可以攻擊伺服器,往往還能夠RCE(遠端命令執行),觸發任意物件構造,任意檔案讀寫,遠端檔案包含,資訊洩露,和提權。

模板注入的成因有兩種:

一:開發人員的錯誤,
二:現有框架為了提供豐富功能而導致暴露過多函式交由使用者操縱。

本文為上述攻擊提供了一套方法論,從漏洞探測到利用漏洞,並且我將例項講解兩個被企業廣泛使用的模板是如何被挖掘出模板注入漏洞。

0x02 介紹


當今web應用頻繁地使用模板系統,諸如Twig,FreeMarket等。當使用者輸入嵌入在一個很沒有安全性的模板時,模板注射就可能發生。

現在我們假設呼叫了Twig框架用來顯示歡迎頁面,如果直接把名字傳遞給模板,不會出現錯誤 就像這樣

#!php
$output = $twig->render("Dear {first_name},", array("first_name" => $user.first_name) );

然而,如果內嵌的名字是由使用者輸入得來的,問題就會出現

#!php
$output = $twig->render($_GET['custom_email'], array("first_name" => $user.first_name) );

在這個例子中,使用者能夠控制$_GET['custom_email'],這時,很多安全審計人員可能就會把它劃歸為一個反射型的Xss,然而,Xss只是表象,只需要改變下利用方式,漏洞其實能夠威脅到伺服器,然而往往這點會被忽略

輸入:custom_email={{7*7}} 
輸出:49

輸入:custom_email={{self}}
輸出:Object of class __TwigTemplate_7ae62e582f8a35e5ea6cc639800ecf15b96c0d6f78db3538221c1145580ca4a5 could not be converted to string

可以看到這裡實際上存在一個遠端程式碼執行(沙箱模式),針對不同的框架,利用不同的語法,繞過沙箱執行任意程式碼是我們的目標。

可能說到這裡,有些人還是不能了理解模板注入以及注入發生的場景。我打了一個這樣不恰當的比方來解釋這個攻擊背景: markdown相信很多人都用過,它支援各種識別符號,讓我們能夠編輯格式,插入圖片,模板注射就是利用我們的markdown的語法,在我們能夠提交markdown文章的網站(drops.wooyun)實施攻擊。

只是說,現在的一些web模板框架更加成熟,其後端語言(php/java)能造成比markdown語言更大的危害,比如說攻擊服務端。

0x03 模板注射之方法論


這裡給出了尋找模板注射的流程圖。

enter image description here

漏洞檢測:

漏洞可能出現在兩種環境

一、可控內容為文字

smarty框架下

輸入:Hello {user.name} 
輸出:Hello user1

freemarker框架下

輸入:Hello ${username}
輸出:Hello newuser

在這種情況下,模糊測試框架的XSS探測結果可以作為發現漏洞的線索,由於黑盒審計攻擊的payload往往是純html或js的,這些地方很容易被誤判成XSS(事實上也是一個xss),要想判別是否是一個模板注入,我們需要利用特定的框架語法來完成漏洞檢測

smarty=Hello ${7*7} 
Hello 49

freemarker=Hello ${7*7}
Hello 49

二、可控內容為程式碼主體

使用者輸入有時候用來構成模板主體,比如說是一個變數名

輸入:personal_greeting=username
輸出:Hello user01

那麼這種情況更容易遺漏,因為此時的自動掃描工具檢測到這裡時,payload根本不會讓模板框架返回一個有效的回顯,你必須遵循特定模板的語法,才能看到頁面的變化,比如這裡我們必須先用}}提前閉合模板程式碼段,才能插入任意一個html的標籤

相關文章