Ruby Mustache Templates RCE
字数 1092 2025-08-27 12:33:42
Ruby Mustache 模板 RCE 漏洞分析与防护指南
1. 漏洞概述
本漏洞并非 Mustache 模板引擎本身的漏洞,而是由于 Ruby Web 应用程序滥用 Mustache 库导致的服务器端模板注入(SSTI)漏洞。攻击者通过控制 Mustache 模板变量,能够实现远程代码执行(RCE),进而读取或删除数据库中的所有客户数据。
2. Mustache 模板基础
Mustache 是一种"无逻辑"模板系统,支持多种编程语言实现:
# 基本用法
Mustache.render("Hello {{name}}!", name: "Rhys") # => "Hello Rhys!"
# 对象方法链访问
user = User.first
Mustache.render("Hello {{user.name}}!", user: user) # => "Hello Rhys!"
3. 漏洞发现过程
3.1 初始发现
- 目标系统接收未经认证的 PagerDuty webhook
- Webhook 数据使用 Mustache 模板渲染为面向客户的通信
- 攻击者可模拟 PagerDuty 服务发送任意内容
3.2 关键突破点
# 发现可以访问 Ruby 对象
Mustache.render("{{context}}", context: some_object)
# 输出: "Mustache::Context:0x00007ffa3b8ef638>"
4. 漏洞利用技术
4.1 基本对象操作
# 查看对象类
Mustache.render("{{value.class}}", value: "Rhys") # => "String"
# 使用 ActiveSupport 的 constantize 方法
Mustache.render("{{value.constantize.new}}", value: "Time")
# => "2019-07-31 12:31:54 -0700"
4.2 利用 ActiveRecord 模型
读取所有客户数据
{{incident.name.constantize.all.first}}
执行流程:
incident.name获取值(如 "Incident")constantize查找对应常量(ActiveRecord 模型)all执行 SQL SELECT 查询first获取第一条记录
删除所有客户数据
{{incident.name.constantize.delete_all}}
5. 限制条件
-
变量名限制:Mustache 变量名只能包含字母、数字和点
- 无法使用需要参数的方法(如
update) - 无法构造复杂表达式如
context.class.ancestors.new.instance_method_send(:eval)
- 无法使用需要参数的方法(如
-
依赖 ActiveSupport:需要目标环境包含 ActiveSupport 的
constantize方法
6. 漏洞修复方案
- 模板标签白名单:只允许预定义的标签在模板中使用
- 沙箱环境渲染:在隔离环境(如 AWS Lambda)中渲染用户提供的模板
- 前端渲染:改用 JavaScript 实现,避免暴露 Ruby 方法链
- 输入过滤:严格验证用户提供的模板内容
7. 防护建议
- 认证与授权:对所有接收 webhook 的端点实施严格认证
- 最小权限原则:模板渲染进程应使用最低必要权限运行
- 日志监控:记录所有模板渲染操作,特别是异常模式
- 定期安全审计:检查模板系统的使用方式是否符合安全规范
8. 总结
此案例展示了即使使用"无逻辑"模板系统,不当的实现方式仍可能导致严重的安全问题。关键在于:
- 永远不要信任用户提供的模板内容
- 限制模板可访问的对象和方法
- 考虑在安全边界外处理不可信内容
通过实施严格的输入验证、输出编码和最小权限原则,可以有效预防此类漏洞。