金盘图书馆管理系统代码审计
字数 4232 2025-10-26 18:21:34
金盘图书馆管理系统代码审计教学文档
文档说明
本教学文档基于公开的金盘图书馆管理系统代码审计文章编写,旨在为安全研究人员、开发人员及学生提供一个完整的代码审计实战案例。文档将遵循代码审计的标准流程,从项目架构分析入手,逐步深入至具体的安全漏洞挖掘与原理分析。
目标读者:具备一定Java Web安全基础,希望提升代码审计能力的人员。
审计对象:金盘图书馆管理系统(基于Spring MVC + JSP架构,使用Shiro进行权限控制)。
第一章:项目架构与配置分析
在开始漏洞挖掘前,必须首先理解项目的技术栈和核心配置,这是定位潜在风险点的基石。
1.1 技术栈识别
- 后端框架:Spring MVC。路由通过
@Controller注解定义,这是审计时关注的重点。 - 前端技术:JSP。需要注意的是,部分业务逻辑可能直接写在JSP中,因此JSP文件也需要纳入审计范围。
- 权限框架:Apache Shiro。这是本项目最关键的组件之一,其配置直接关系到系统的访问控制安全。
- 指纹特征:在FOFA等网络空间测绘引擎中,可使用
"/opac/search/autoFill?field=title"作为识别此系统的指纹。
1.2 关键配置文件解析
web.xml:这是Web应用的部署描述文件,是所有审计的起点。- 核心任务:分析其中配置的
<filter>和<filter-mapping>。 - 审计发现:文章中提到了多个Filter,其中最重要的是与Shiro相关的过滤器链和一个名为
CAS助手过滤器的自定义过滤器。这些过滤器的配置决定了请求的拦截和放行规则。
- 核心任务:分析其中配置的
1.3 权限架构深度分析
权限控制是安全的门户,分析不当会导致严重的未授权访问漏洞。
-
Shiro 配置分析:
- 文章中提及,Shiro被配置为全局拦截,但其规则可能只明确拦截了
/admin路径下的请求。这意味着/admin以外的路径理论上可以未经认证直接访问。这种“黑名单”式的配置思路极易导致权限绕过。 - 版本风险:通过分析依赖(如pom.xml或lib目录下的jar包),确认Shiro版本为1.2.1。这是一个非常古老的版本,存在著名的Shiro-550(反序列化)漏洞以及多个历史鉴权绕过漏洞。
- 文章中提及,Shiro被配置为全局拦截,但其规则可能只明确拦截了
-
自定义过滤器分析(CAS助手过滤器):
- 功能:该过滤器会从
web.xml的初始化参数中读取excludePrefixes(排除路径前缀)和excludeExtentions(排除文件后缀)。 - 绕过原理:如果请求的资源路径匹配排除列表中的前缀,或者请求的文件后缀匹配排除列表(如
.js),则请求会被放行。 - 经典绕过手法:利用路径解析的差异性。例如,访问
/admin/secretInterface;.js,过滤器检查后缀.js,认为这是一个静态资源而放行,但Spring MVC可能仍将其路由到/admin/secretInterface对应的Controller。这就造成了权限绕过。
- 功能:该过滤器会从
第二章:漏洞挖掘与详解
本章将逐一分解文章中发现的各类安全漏洞,并解释其成因、利用方法和危害。
2.1 高危漏洞:Shiro反序列化(Shiro-550)
- 漏洞原理:Shiro 1.2.4之前版本使用了硬编码的AES加密密钥。攻击者如果能够获取到
RememberMeCookie,就可以对其进行反序列化攻击,在目标服务器上执行任意命令。 - 审计步骤:
- 确认版本:检查Shiro版本是否低于1.2.4。
- 搜索密钥:在代码中全局搜索关键字
setCipherKey、cipherKey等,确认是否使用了默认密钥kPH+bIxk5D2deZiIxcaaaA==。文章指出密钥内嵌在Jar包中,符合漏洞条件。
- 利用方式:使用公开工具(如YSOSERIAL)生成恶意序列化数据,用默认密钥加密后替换Cookie中的
rememberMe字段发送给服务器。
2.2 高危漏洞:任意文件上传
文章中共发现三处任意文件上传点,均因对上传文件的文件名处理不当所致。
-
第一处:
ShlefController.java中的uploadimg方法- 漏洞点:使用
file.getOriginalFilename()获取原始文件名,虽然之后调用了generateFileName方法生成随机文件名,但关键在于此接口未受权限控制。 - 审计技巧:即使后端对文件名进行了重命名,只要攻击者能控制文件内容和服务器上的存储路径,并且该路径能被Web服务器解析,就存在上传Webshell的风险。需确认接口的访问权限。
- 漏洞点:使用
-
第二处:
OpacUploadController.java中的upload方法- 漏洞点:文件名处理逻辑为
uploadTime + fileName.substring(fileName.indexOf(46))。其中46是字符.的ASCII码。这意味着它直接截取原始文件名中第一个点之后的部分作为后缀。 - 风险:攻击者可上传名为
shell.jsp.jpg的文件,后缀被截取为.jpg,但某些环境(如旧版Tomcat)可能仍会以JSP解析。更安全的方式应使用白名单机制校验后缀。
- 漏洞点:文件名处理逻辑为
-
第三处:
pages/admin/tools/uploadFile/doUpload.jsp- 漏洞点:该JSP页面包含一个黑名单检查,禁止文件名中包含
jsp。 - 绕过技巧:
- URL编码:
test.jsp->test.%6A%73%70 - Unicode编码:
test.jsp->test.\u006A\u0073\u0070
- URL编码:
- 审计思考:黑名单机制往往存在被绕过的风险。此处的代码逻辑被文章作者评价为“怪怪的”,说明二开代码的质量可能不高,更容易出现疏漏。
- 漏洞点:该JSP页面包含一个黑名单检查,禁止文件名中包含
2.3 中危漏洞:Zip解压任意文件写入(目录穿越)
- 漏洞位置:
FileController.java中的unzipFile方法调用了ZipUtil.java中的unzip方法。 - 漏洞成因:解压压缩包时,未对压缩包内文件的文件名进行合法性校验。攻击者可以构造一个包含恶意文件(如
.jspWebshell)或带有路径穿越字符(如../../../WEB-INF/web.xml)的压缩包。 - 危害:可能导致Webshell上传或关键系统文件被覆盖,结合其他漏洞可提升危害等级。
2.4 中危漏洞:任意文件读取与删除
-
任意文件读取
- 位置:
pages/admin/tools/file/download.jsp - 漏洞点:该页面直接接收用户传入的
items参数(文件路径),未经过滤就用于创建FileInputStream来读取文件内容。未检查路径是否包含../等穿越字符。 - 利用:可读取服务器上的任意文件,如配置文件(
/WEB-INF/web.xml、数据库连接文件)、密码文件等。
- 位置:
-
任意文件删除
- 位置:
FileController.java中的delete方法调用了FileUtil.deleteFile。 - 漏洞点:直接使用用户传入的
file参数进行删除操作,未做路径规范化或合法性校验。 - 危害:攻击者可删除应用关键文件,导致服务瘫痪(拒绝服务攻击),或为后续攻击铺平道路。
- 位置:
2.5 严重漏洞:任意命令执行
- 位置:一个二开功能的JSP文件,如
vim.jsp。 - 漏洞点:代码中直接使用
Runtime.getRuntime().exec()执行用户通过HTTP参数传入的命令。虽然文中提到有一个简单的密码检查(判断p是否为xxxx),但这个密码同样是通过参数传入,非常容易被绕过或猜测。 - 审计总结:在代码中全局搜索
Runtime.getRuntime().exec()、ProcessBuilder等关键字,是发现命令执行漏洞最直接有效的方法。对于二开代码和管理后台的工具类页面要特别关注。
第三章:代码审计方法论总结
通过本案例,我们可以提炼出以下通用的代码审计方法论:
- 始于配置:从
web.xml和框架配置文件(如shiro.ini、spring.xml)入手,理解应用的权限边界和请求处理流程。 - 关注入口点:重点审计
Controller和Servlet,特别是涉及文件操作、数据库查询、命令执行、用户输入处理的接口。 - 追踪用户输入:牢记“数据从不可信来源到危险函数”的流动路径。用户输入(如
HttpServletRequest.getParameter()、@RequestParam)是否经过充分校验?是否最终流入FileOutputStream、Runtime.exec()、SQL语句等危险函数? - 警惕权限缺失:对每一个业务接口,都要问一句“这个接口做了权限校验吗?”。特别注意那些不在标准管理路径下(如
/admin)但功能敏感的接口。 - 版本决定漏洞:识别所有第三方组件的版本(Shiro、Fastjson、Struts2等),比对已知的公开漏洞。
- 二开代码是富矿:项目自定义或二次开发的代码,往往安全意识薄弱,逻辑复杂,是漏洞的高发区。
第四章:修复建议
针对发现的漏洞,提出以下修复建议:
- 整体权限:采用“默认拒绝”的白名单策略,为所有敏感接口添加明确的权限注解。升级Shiro至最新安全版本。
- 文件上传:使用白名单校验文件后缀;对上传文件重命名(如使用UUID);将文件存储在Web根目录之外,通过后端接口进行访问。
- 文件操作:对用户输入的路径进行标准化(如使用
File.getCanonicalPath()),并检查是否在允许的目录范围内。 - 命令执行:绝对避免直接执行用户输入的命令。如果业务必需,应严格使用白名单限制可执行的命令和参数。
- Zip解压:在解压前,校验压缩包内每个文件的文件名,拒绝包含路径穿越字符或非法后缀的文件。
希望这份详尽的教学文档能帮助您系统地掌握代码审计的技巧。审计是一个需要耐心和细心的过程,祝您在安全研究的道路上不断进步!