对Java CMS的审计的一次尝试
字数 2109 2025-08-26 22:11:35
Java CMS安全审计实战教学文档
1. 环境搭建
-
项目导入:
- 使用IDEA开发工具导入项目
- MySQL中新建ofcms数据库
-
数据库配置:
- 修改
ofcms-admin模块中的配置文件:- 路径:
src/main/resources/conf/dev/conf/db-config.properties - 重命名为
db.properties - 配置JDBC连接信息
- 路径:
- 修改
-
数据库初始化:
- 两种方式可选:
- 手工方式:执行
doc/sql文件夹中的SQL文件 - 自动方式(本文选择手工方式)
- 手工方式:执行
- 两种方式可选:
-
启动项目:
- 使用Tomcat容器启动项目
- 管理后台默认凭证:
admin/123456
2. 组件分析
2.1 FreeMarker模板引擎
- 存在模板注入(SSTI)风险
- 攻击场景:通过修改模板文件实现攻击
3. 漏洞审计
3.1 FreeMarker模板注入(SSTI)
漏洞位置
- 后台模板编辑功能
- 相关控制器:
com.ofsoft.cms.admin.controller.cms.TemplateController#save
攻击流程
-
请求处理流程:
- Tomcat容器处理请求
- Shiro组件进行鉴权(访问
/admin路径) - 返回Tomcat进行Filter链调用
- 最终调用
save方法
-
关键代码分析:
// 获取res_path参数值并与"res"比较 // 根据比较结果获取模板文件目录(resource或webapp下) // 获取模板文件相对路径(dirs) // 拼接模板文件目录和相对路径 // 获取模板文件名和内容 // 将编码复原为<>等符号 // 调用FileUtils#writeString写入文件 -
漏洞利用:
- 修改模板文件内容为恶意代码
- 例如:
${ex("calc")}(执行计算器) - 访问404.html触发模板渲染
-
调用栈分析:
- 渲染流程最终调用
Execute#exec执行命令 - 关键调用链:
FreeMarkerRender#render → Environment#process → MixedContent#accept → DollarVariable#accept → Expression#evalAndCoerceToString → Execute#exec
- 渲染流程最终调用
防御措施
- 添加WAF进行拦截
- 使用
TemplateClassResolver限制可解析类- 文档参考:https://freemarker.apache.org/docs/api/freemarker/core/TemplateClassResolver.html
- 注意
?api配置可能导致绕过
3.2 任意文件上传
漏洞位置
- 模板编辑功能中的文件保存操作
- 同一
TemplateController#save方法
漏洞分析
-
关键问题:
- 无过滤措施:
- 无路径穿越防护
- 无文件后缀限制
- 无危险函数检测
- 无过滤措施:
-
利用方式:
- 通过控制
dirs参数实现目录穿越 - 指定恶意文件名(如
shell.jsp) - 写入Web目录实现webshell上传
- 通过控制
防御措施
- 禁止目录穿越
- 严格检测文件后缀名
- 部署webshell查杀机制
3.3 存储型XSS
漏洞位置
- 评论功能
- 相关控制器:
CommentApi#save
漏洞分析
-
处理流程:
- 调用
getParamsMap获取评论内容 - 添加评论者IP地址
- 执行
Db.update方法存入数据库
- 调用
-
SQL处理细节:
- 使用预编译SQL防止注入
- 但未对评论内容进行XSS过滤
- 导致存储型XSS
-
影响范围:
- 几乎所有可评论位置都存在此漏洞
- 新闻页面渲染时会执行恶意脚本
防御措施
- 严格校验写入数据库的内容
- 实现HTML实体编码
- 使用专业XSS过滤库
3.4 CSRF漏洞
漏洞表现
- 所有操作均未使用CSRF-Token防护
- 可通过构造恶意页面实现跨站请求伪造
防御措施
- 验证HTTP Referer字段
- 添加CSRF-Token机制
- HTTP头中添加自定义属性验证
3.5 SQL注入
漏洞位置
- 后台代码生成功能
- 相关控制器:
SystemGenerateController#create
漏洞分析
-
执行流程:
- 获取
sql参数值 - 调用
Db.update执行SQL - 通过
DbPro#update方法最终执行
- 获取
-
可利用的SQL类型:
- UPDATE
- INSERT
- DELETE
-
利用方式:
- 使用报错注入技术
- 示例Payload:
update of_cms_link set link_name = updatexml(1,concat(0x7e,(user())),0) where link_id = 4
-
问题根源:
- 虽然使用预编译但未发挥应有作用
- 直接拼接用户输入执行
防御措施
- 严格过滤用户输入
- 使用最小权限数据库账户
- 实现SQL关键字过滤
4. 总结
4.1 漏洞汇总表
| 漏洞类型 | 风险等级 | 位置 | 防御建议 |
|---|---|---|---|
| FreeMarker SSTI | 高危 | 模板编辑功能 | 限制模板解析类 |
| 任意文件上传 | 高危 | 模板保存功能 | 路径/后缀名限制 |
| 存储型XSS | 中危 | 评论功能 | 输入过滤/输出编码 |
| CSRF | 中危 | 全站操作 | 添加CSRF-Token |
| SQL注入 | 高危 | 代码生成功能 | 输入过滤/权限控制 |
4.2 通用防御建议
-
输入验证:
- 所有用户输入都应视为不可信的
- 实现白名单验证机制
-
输出编码:
- 根据输出上下文进行适当编码
- HTML/JavaScript/URL等不同场景使用不同编码
-
安全配置:
- 组件安全配置(如FreeMarker的TemplateClassResolver)
- 最小权限原则
-
安全开发:
- 使用安全框架提供的基础功能
- 定期安全代码审计
-
防御纵深:
- WAF防护
- 定期漏洞扫描
- 安全监控与日志审计