从0到1挖掘freemaker 模板注入
字数 1717 2025-08-29 08:30:13

FreeMarker 模板注入漏洞分析与利用

1. DataGear 简介

DataGear 是一款开源免费的数据可视化分析平台,具有以下特点:

  • 支持多种数据源:SQL、CSV、Excel、HTTP 接口、JSON等
  • 支持多种数据库:MySQL、Oracle、PostgreSQL、SQL Server等
  • 提供70+开箱即用的图表类型
  • 支持自定义HTML网页作为数据看板模板

2. FreeMarker 模板注入漏洞原理

2.1 FreeMarker 的 new 内置函数

FreeMarker 模板引擎中的 new 关键字用于创建新的实例对象:

  • 可以实例化Java类
  • 可以在创建对象时直接调用构造函数初始化属性
  • 允许在模板中动态创建Java对象

2.2 危险内置类

FreeMarker 提供了几个危险的辅助类:

2.2.1 freemarker.template.utility.ObjectConstruct

  • 用于创建Java对象并转换为FreeMarker模板数据模型
  • 允许模板动态实例化对象

2.2.2 freemarker.template.utility.JythonRuntime

  • 用于与Jython(基于Java的Python解释器)交互
  • 允许模板执行Python脚本

2.2.3 freemarker.template.utility.Execute

  • 重写了Writer类的flush和close方法
  • 接收的字符序列会被附加到StringBuilder缓冲区
  • 调用flush时会执行缓冲区内容作为Python代码

2.3 利用方式

基于new构建对象的三种payload:

  1. 使用<#assign>标签定义变量:

    <#assign value="freemarker.template.utility.ObjectConstructor"?new()>
    
  2. 使用JythonRuntime执行Python代码:

    <#assign value="freemarker.template.utility.JythonRuntime"?new()>
    
  3. 使用Execute执行系统命令:

    <#assign value="freemarker.template.utility.Execute"?new()>
    

2.4 API 内置函数

api内建函数用于调用Java API:

  • 允许模板访问和调用Java类及其方法
  • 可以获取当前对象的类加载器
  • 从FreeMarker 2.3.22开始默认禁用

示例payload:

<#assign classLoader=object?api.class.protectionDomain.classLoader>

3. 漏洞复现

3.1 漏洞位置

漏洞存在于DataGear的/dataSet/resolveSql路由,对应代码位于:
org/datagear/web/controller/DataSetController.java

3.2 漏洞触发流程

  1. 接收请求参数:通过@RequestBody接收ResolveSqlParam对象
  2. 调用解析方法:将参数传递给resolveSqlTemplate方法进行SQL解析
  3. SQL解析过程:
    • DataSetFmkTemplateResolvers.SQL.resolve解析SQL语句
    • SQL查询语句作为实例化TemplateContext的参数
    • 通过getValues获取模板内容并解析
    • 将模板封装在templateObj对象中
    • 调用process方法解析value

3.3 命令执行

在模板解析过程中,当循环到最内层内容时,会执行注入的命令,并将执行结果作为模板渲染的结果返回。

4. 漏洞利用示例

4.1 环境搭建

  1. 下载DataGear源码:https://gitee.com/datagear/datagear
  2. 导入IDEA,使用Maven构建
  3. 创建数据库并启动应用

4.2 执行系统命令

使用以下payload可以执行任意系统命令:

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("cmd /c whoami") }

成功执行后会返回命令执行结果。

5. 漏洞分析

5.1 关键代码分析

  1. DataSetController.java中的resolveSql方法:

    public String resolveSql(@RequestBody ResolveSqlParam resolveSqlParam)
    
  2. resolveSqlTemplate方法:

    private String resolveSqlTemplate(String sql, Map<String, Object> paramValues, List<DataSetParam> dataSetParams)
    
  3. 模板解析过程:

    TemplateContext templateContext = new TemplateContext(sql, paramValues, dataSetParams);
    return DataSetFmkTemplateResolvers.SQL.resolve(templateContext);
    

5.2 安全建议

  1. 升级FreeMarker到最新版本
  2. 禁用危险的内置函数和类
  3. 对用户输入进行严格的过滤和验证
  4. 使用沙箱环境限制模板的执行权限

6. 总结

DataGear中的FreeMarker模板注入漏洞源于对用户输入的不当处理,攻击者可以通过构造特殊的模板表达式实现任意命令执行。开发人员应当重视模板引擎的安全配置,避免直接使用用户输入作为模板内容。

FreeMarker 模板注入漏洞分析与利用 1. DataGear 简介 DataGear 是一款开源免费的数据可视化分析平台,具有以下特点: 支持多种数据源:SQL、CSV、Excel、HTTP 接口、JSON等 支持多种数据库:MySQL、Oracle、PostgreSQL、SQL Server等 提供70+开箱即用的图表类型 支持自定义HTML网页作为数据看板模板 2. FreeMarker 模板注入漏洞原理 2.1 FreeMarker 的 new 内置函数 FreeMarker 模板引擎中的 new 关键字用于创建新的实例对象: 可以实例化Java类 可以在创建对象时直接调用构造函数初始化属性 允许在模板中动态创建Java对象 2.2 危险内置类 FreeMarker 提供了几个危险的辅助类: 2.2.1 freemarker.template.utility.ObjectConstruct 用于创建Java对象并转换为FreeMarker模板数据模型 允许模板动态实例化对象 2.2.2 freemarker.template.utility.JythonRuntime 用于与Jython(基于Java的Python解释器)交互 允许模板执行Python脚本 2.2.3 freemarker.template.utility.Execute 重写了Writer类的flush和close方法 接收的字符序列会被附加到StringBuilder缓冲区 调用flush时会执行缓冲区内容作为Python代码 2.3 利用方式 基于 new 构建对象的三种payload: 使用 <#assign> 标签定义变量: 使用JythonRuntime执行Python代码: 使用Execute执行系统命令: 2.4 API 内置函数 api 内建函数用于调用Java API: 允许模板访问和调用Java类及其方法 可以获取当前对象的类加载器 从FreeMarker 2.3.22开始默认禁用 示例payload: 3. 漏洞复现 3.1 漏洞位置 漏洞存在于DataGear的 /dataSet/resolveSql 路由,对应代码位于: org/datagear/web/controller/DataSetController.java 3.2 漏洞触发流程 接收请求参数:通过 @RequestBody 接收 ResolveSqlParam 对象 调用解析方法:将参数传递给 resolveSqlTemplate 方法进行SQL解析 SQL解析过程: DataSetFmkTemplateResolvers.SQL.resolve 解析SQL语句 SQL查询语句作为实例化 TemplateContext 的参数 通过 getValues 获取模板内容并解析 将模板封装在 templateObj 对象中 调用 process 方法解析value 3.3 命令执行 在模板解析过程中,当循环到最内层内容时,会执行注入的命令,并将执行结果作为模板渲染的结果返回。 4. 漏洞利用示例 4.1 环境搭建 下载DataGear源码:https://gitee.com/datagear/datagear 导入IDEA,使用Maven构建 创建数据库并启动应用 4.2 执行系统命令 使用以下payload可以执行任意系统命令: 成功执行后会返回命令执行结果。 5. 漏洞分析 5.1 关键代码分析 DataSetController.java 中的 resolveSql 方法: resolveSqlTemplate 方法: 模板解析过程: 5.2 安全建议 升级FreeMarker到最新版本 禁用危险的内置函数和类 对用户输入进行严格的过滤和验证 使用沙箱环境限制模板的执行权限 6. 总结 DataGear中的FreeMarker模板注入漏洞源于对用户输入的不当处理,攻击者可以通过构造特殊的模板表达式实现任意命令执行。开发人员应当重视模板引擎的安全配置,避免直接使用用户输入作为模板内容。