FreeMarker模板注入

简介: FreeMarker模板注入

一、简介


FreeMarker是一款模板引擎,通过Java类库引入,模板文件简称为FTL(后缀可能也为这个)。输出方式为MVC(模型,视图,控制器)模式,适用于Web开发框架生成html页面。所以此类库经常应用于MVC开发模式的Java Web程序。


二、利用与发掘


既然简介为模板引擎,那么就一定有可以动态利用的地方。FreeMarker动态处理变量为${}格式,当然还有标签格式,这个稍后讲解。看到这里,是不是很像el、spel引擎模板的解析风格,不过确实有相似部分,当然也有区别。接下来,通过代码分析利用方式或常见格式:


Configuration configuration = new Configuration();
String templateContent = "${1+1}";
Template tpl = new Template(null, templateContent, configuration);
StringWriter writer = new StringWriter();
tpl.process(null, writer);
System.out.println(writer);

f48a2ecb4ae561fc940b03783642089a_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


可以看到成功执行表达式并输出结果,FreeMarker与el、spel的区别这时就体现了,虽然检测漏洞时都可以利用类似表达式,但是执行命令时又有不同,FreeMarker在process执行时必须继承freemarker.template.TemplateModel,如下图报错所示:


10a9643130b538a64d03ac84dde3dce2_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


那么FreeMarker执行命令的方式有哪些呢,可以直接通过TemplateModel反推继承链,看看哪些类中的方法存在可以利用的方式,从上图报错中可以回溯执行的调用过程


at freemarker.core.Expression.eval(Expression.java:78)
at freemarker.core.MethodCall._eval(MethodCall.java:55)
at freemarker.core.Expression.eval(Expression.java:78)
at freemarker.core.Expression.evalAndCoerceToString(Expression.java:82)
at freemarker.core.DollarVariable.accept(DollarVariable.java:41)
at freemarker.core.Environment.visit(Environment.java:324)
at freemarker.core.Environment.process(Environment.java:302)
at freemarker.template.Template.process(Template.java:325)
at com.cc.demo.spel.main(spel.java:37)

跟踪到MethodCall中_eval方法,在继承了TemplateModel类时最终会执行到对应类的exec方法中,这里直接贴出可利用的类(既继承TemplateModel类又存在exec方法,方法中存在执行命令)得到:


freemarker.template.utility.Execute
freemarker.template.utility.ObjectConstructor
freemarker.template.utility.JythonRuntime

当然这是一种执行方式,还有官方

https://freemarker.apache.org/docs/ref_builtins_expert.html)的标签执行。


当然还有一些变量参考

https://freemarker.apache.org/docs/ref_specvar.html)。官方文档还是很管用的。


三、限制


既然官方已知含有危险方法并可执行,那么就一定会有限制解决的方案,在2.3.17版本中加入了setNewBuiltinClassResolver方法,此方法可以限制最后的执行类,有多种格式可以选择,例如


configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDefaultEncoding(CommonConstants.DEFAULT_CHARSET_NAME);
configuration.setTemplateUpdateDelayMilliseconds(0);
configuration.setAPIBuiltinEnabled(false);
configuration.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
configuration.setLogTemplateExceptions(false);

第一行设置config版本(可以忽略不设置),第二行设置编码格式,第三行设置模板更新缓存延迟,第四行设置API权限,第五行设置可以加载类,第六行设置异常log输出。重点在第四行与第五行,第四行中的api可访问Java Api FreeMarker中object_wrapper(根据环境不同,可能存在利用方式),第五行中


ALLOWS_NOTHING_RESOLVER

为禁止解析任何类,对应还有


UNRESTRICTED_RESOLVE

等于


ClassUtil.forName(className)

和SAFER_RESOLVER禁止解析上述命令执行的三个类。


四、突破


上述讲解了限制,既然有限制,必然就要想到应对之策,从官方的变量参考中,找到了一些可以利用的点,例如get_optional_template特殊变量,官方文档中描述:

This method returns a hash that contains the following entries:



exists: A boolean that tells if the template was found.



include: A directive that, when called, includes the template. Calling this directive is similar to calling the include directive, but of course with this you spare looking up the template again. This directive has no parameters, nor nested content. If exists is false, this key will be missing; see later how can this be utilized with the exp!default operator.



import: A method that, when called, imports the template, and returns the namespace of the imported template. Calling this method is similar to calling the import directive, but of course with this you spare looking up the template again, also, it doesn't assign the namespace to anything, just returns it. The method has no parameters. If exists is false, this key will be missing; see later how can this be utilized with the exp!default operator.


变量可以包含模板文件以及import method,类似PHP中的include方法,这时利用方式就有很多了,可以发散思维到PHP文件包含漏洞等等,利用方式可以参考官方,也可更新一下使用

<#assign optTemp = .get_optional_template('some.ftl')>
<#if optTemp.exists>
Template was found:
<@optTemp.include />
<#else>
Template was missing.
</#if>

相关文章
|
Java 关系型数据库 API
Spring模板对象Template
Spring模板对象Template
57 0
|
Java Maven
springboot项目--freemarker使用ftl模板文件动态生成图片
springboot项目--freemarker使用ftl模板文件动态生成图片
831 0
|
前端开发 Java
SpringBoot-6-模板Thymeleaf常用标签
SpringBoot-6-模板Thymeleaf常用标签
93 0
SpringBoot-6-模板Thymeleaf常用标签
|
Python
SSTI模板注入
SSTI模板注入
90 1
|
前端开发 Java
Freemarker - 基础篇(上)
Freemarker - 基础篇(上)
393 0
Freemarker - 基础篇(上)
|
前端开发
Freemarker - 基础篇(下)
Freemarker - 基础篇(下)
211 0
Freemarker - 基础篇(下)
|
Java Android开发 Spring
spring练习,使用Eclipse搭建的Spring开发环境,使用set注入方式为Bean对象注入属性值并打印输出。
spring练习,使用Eclipse搭建的Spring开发环境,使用set注入方式为Bean对象注入属性值并打印输出。
158 0
spring练习,使用Eclipse搭建的Spring开发环境,使用set注入方式为Bean对象注入属性值并打印输出。
|
Java 数据库
FreeMarker 模板来定义字符串模板
FreeMarker 模板来定义字符串模板
348 0
FreeMarker 模板来定义字符串模板
|
Java 程序员 索引
Spring的三种创建方式和各种属性的注入(二)
Spring的三种创建方式和各种属性的注入(二)
125 0
Spring的三种创建方式和各种属性的注入(二)
|
XML Java 数据格式
初识 Spring(03)---(XML注入方式 / 注入类型)
XML注入方式 1.set 方式注入  2.构造方式注入  3.工厂方式注入 set 方式注入 1.ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.
1113 0