金盘图书馆管理系统代码审计
字数 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(反序列化)漏洞以及多个历史鉴权绕过漏洞。
  • 自定义过滤器分析(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加密密钥。攻击者如果能够获取到RememberMe Cookie,就可以对其进行反序列化攻击,在目标服务器上执行任意命令。
  • 审计步骤
    1. 确认版本:检查Shiro版本是否低于1.2.4。
    2. 搜索密钥:在代码中全局搜索关键字setCipherKeycipherKey等,确认是否使用了默认密钥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
    • 审计思考:黑名单机制往往存在被绕过的风险。此处的代码逻辑被文章作者评价为“怪怪的”,说明二开代码的质量可能不高,更容易出现疏漏。

2.3 中危漏洞:Zip解压任意文件写入(目录穿越)

  • 漏洞位置FileController.java 中的 unzipFile 方法调用了 ZipUtil.java 中的 unzip 方法。
  • 漏洞成因:解压压缩包时,未对压缩包内文件的文件名进行合法性校验。攻击者可以构造一个包含恶意文件(如 .jsp Webshell)或带有路径穿越字符(如 ../../../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 等关键字,是发现命令执行漏洞最直接有效的方法。对于二开代码和管理后台的工具类页面要特别关注。

第三章:代码审计方法论总结

通过本案例,我们可以提炼出以下通用的代码审计方法论:

  1. 始于配置:从web.xml和框架配置文件(如shiro.inispring.xml)入手,理解应用的权限边界和请求处理流程。
  2. 关注入口点:重点审计ControllerServlet,特别是涉及文件操作、数据库查询、命令执行、用户输入处理的接口。
  3. 追踪用户输入:牢记“数据从不可信来源到危险函数”的流动路径。用户输入(如HttpServletRequest.getParameter()@RequestParam)是否经过充分校验?是否最终流入FileOutputStreamRuntime.exec()SQL语句等危险函数?
  4. 警惕权限缺失:对每一个业务接口,都要问一句“这个接口做了权限校验吗?”。特别注意那些不在标准管理路径下(如/admin)但功能敏感的接口。
  5. 版本决定漏洞:识别所有第三方组件的版本(Shiro、Fastjson、Struts2等),比对已知的公开漏洞。
  6. 二开代码是富矿:项目自定义或二次开发的代码,往往安全意识薄弱,逻辑复杂,是漏洞的高发区。

第四章:修复建议

针对发现的漏洞,提出以下修复建议:

  • 整体权限:采用“默认拒绝”的白名单策略,为所有敏感接口添加明确的权限注解。升级Shiro至最新安全版本。
  • 文件上传:使用白名单校验文件后缀;对上传文件重命名(如使用UUID);将文件存储在Web根目录之外,通过后端接口进行访问。
  • 文件操作:对用户输入的路径进行标准化(如使用File.getCanonicalPath()),并检查是否在允许的目录范围内。
  • 命令执行:绝对避免直接执行用户输入的命令。如果业务必需,应严格使用白名单限制可执行的命令和参数。
  • Zip解压:在解压前,校验压缩包内每个文件的文件名,拒绝包含路径穿越字符或非法后缀的文件。

希望这份详尽的教学文档能帮助您系统地掌握代码审计的技巧。审计是一个需要耐心和细心的过程,祝您在安全研究的道路上不断进步!

金盘图书馆管理系统代码审计教学文档 文档说明 本教学文档基于公开的金盘图书馆管理系统代码审计文章编写,旨在为安全研究人员、开发人员及学生提供一个完整的代码审计实战案例。文档将遵循代码审计的标准流程,从项目架构分析入手,逐步深入至具体的安全漏洞挖掘与原理分析。 目标读者 :具备一定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(反序列化)漏洞以及多个历史鉴权绕过漏洞。 自定义过滤器分析(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加密密钥。攻击者如果能够获取到 RememberMe Cookie,就可以对其进行反序列化攻击,在目标服务器上执行任意命令。 审计步骤 : 确认版本 :检查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 审计思考 :黑名单机制往往存在被绕过的风险。此处的代码逻辑被文章作者评价为“怪怪的”,说明二开代码的质量可能不高,更容易出现疏漏。 2.3 中危漏洞:Zip解压任意文件写入(目录穿越) 漏洞位置 : FileController.java 中的 unzipFile 方法调用了 ZipUtil.java 中的 unzip 方法。 漏洞成因 :解压压缩包时,未对压缩包内文件的文件名进行合法性校验。攻击者可以构造一个包含恶意文件(如 .jsp Webshell)或带有路径穿越字符(如 ../../../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解压 :在解压前,校验压缩包内每个文件的文件名,拒绝包含路径穿越字符或非法后缀的文件。 希望这份详尽的教学文档能帮助您系统地掌握代码审计的技巧。审计是一个需要耐心和细心的过程,祝您在安全研究的道路上不断进步!