某ERP系统源码审计与漏洞分析全过程记录
字数 3949 2025-09-23 19:27:46

某自研ERP系统Java源码安全审计与漏洞挖掘实战教学文档

文档说明

本文档基于安全研究人员“FyW06nIyAt”对某自研Java ERP系统的源码审计实战记录整理而成。旨在系统性地讲解该框架的特点、核心机制,并详细剖析其中存在的安全漏洞,为安全研究人员、开发人员及初学者提供一份详尽的代码审计实战指南。本文档遵循“关键点不遗漏”的原则,专注于技术细节与漏洞成因。

一、 系统与框架概览

1.1 基本特征

  • 技术栈: Java Web项目。
  • 数据库: 通常使用 Oracle 或 MS SQL Server。
  • 鉴权方式: 基于 Session 的访问控制。
  • 核心特点: 采用自研框架,其最大特色在于通过一个名为 FormService 的中央Servlet,利用反射机制动态调用后端服务方法,实现前后端功能点的灵活交互。

1.2 关键指纹与鉴权方式

系统通过一个名为 PortalFilter 的过滤器对访问进行初步控制。

  • 受控后缀: 对包含 .jsp, .do, .action, .ajax 等特定后缀的URL请求进行拦截。
  • 鉴权逻辑: 过滤器检查用户Session是否存在。若Session不存在且请求的URL包含上述受控后缀,则抛出异常并重定向到登录页面。
  • 审计启示: 此鉴权仅针对明确定义的路由后缀。许多通过反射机制调用的后台功能点并未直接关联这些后缀,因此可能绕过此过滤器的基础鉴权,这是审计中需要重点关注的方向。

二、 核心机制:反射调用与鉴权 (FormService)

com.artery.form.FormService 是整个系统审计的核心入口,它本质上是一个Servlet。

2.1 核心功能

负责接收前端所有与表单相关的请求,通过解析参数,使用反射(Reflection) 动态定位并调用后端对应的Java类和方法,最终将执行结果以XML格式返回给前端。它是连接前端请求与后端业务逻辑的“中间层”或“API网关”。

2.2 调用流程与分析

  1. 读取配置: 从 plugins.xml 等配置文件中读取服务映射关系。
  2. 解析服务名: 从前端传入的 service 参数中解析出需要调用的服务组(Group)方法名(Method)
  3. 反射获取方法: 通过 Class.getMethod() 等方法,根据解析出的类名和方法名,获取目标 Method 对象。
  4. 参数处理: 确定目标方法的参数类型。前端数据主要通过 content 参数传入,系统会根据 Content-Type 头(如 application/xmlapplication/json)来解析 content 的内容并转换为方法所需的参数对象。
  5. 方法缓存: 会将反射获取到的 Method 对象缓存到Map中,提升后续调用效率。

2.3 关键鉴权机制 (isAccessible)

这是审计前台漏洞的黄金法则。

  • 在通过反射调用目标方法前,系统会尝试检查该方法是否定义了一个名为 isAccessible 的方法。
  • isAccessible() 方法的作用是判断当前请求是否有权限访问该功能。如果该方法返回 true 或存在某些允许的逻辑,则允许匿名访问。
  • 漏洞利用前提: 只要找到一个不存在 isAccessible 方法 或者 isAccessible 方法逻辑存在缺陷的 public 方法,且该方法本身含有安全风险(Sink点),就可能实现未授权访问

三、 漏洞详解与复现分析

以下漏洞均基于绕过 FormService 的鉴权机制进行利用。

3.1 任意文件上传漏洞

漏洞点一: com.artery.util.ServletUpload

  • 漏洞方法: 该类的文件上传方法。
  • 技术细节: 使用 DiskFileItemFactory 处理文件上传。
  • 漏洞成因: 上传文件时,会调用 bbswriteFileItem() 方法,该方法继续调用 bbsregisterAttachment()。在此方法中,系统为上传的文件生成一个文件名后,未对文件后缀名进行任何校验或过滤,直接将文件内容写入磁盘。
  • 利用方式: 通过 FormService 构造请求,调用该上传功能,上传恶意文件(如 .jsp 木马)。

漏洞点二: com.qy960.service.BBSService#phoneUpload

  • 漏洞方法: phoneUpload 方法。
  • 技术细节: 同样使用 DiskFileItemFactory
  • 漏洞成因: 与漏洞点一类似,最终也调用了未做后缀校验的 bbswriteFileItem() 方法。
  • 利用特点: 该方法返回的是上传后的文件名,但上传路径(path)可能不易直接获取,需要结合其他漏洞(如目录遍历读取)或进行路径爆破。

3.2 任意文件读取/目录遍历漏洞

漏洞点: com.artery.form.services.FormStudioUpdater#getStudioFile

  • 漏洞方法: getStudioFile
  • 参数: 接收 fileStr 参数,该参数直接用于文件路径拼接。
  • 漏洞成因: 方法内部未对 fileStr 参数中的 ../ 等序列进行过滤,导致目录遍历,可以读取服务器上的任意文件(如 ../../../../etc/passwd)。
  • 数据传输: 由于通过 FormService 调用,参数需通过 content 参数以特定格式(如XML)传入。
  • 请求构造建议: 由于传输的是XML格式数据,将请求的 Content-Type 设置为 application/xml 并构造相应的XML payload是最佳方式。

3.3 SQL注入漏洞 (前台)

漏洞点: com.artery.workflow.ServiceImpl#sqlResult

  • 漏洞方法: sqlResult
  • 参数: 接收外部传入的 sql 参数。
  • 漏洞成因: 方法内部直接将可控的 sql 参数传入 getFieldValue() 方法中,该方法最终会执行这个SQL字符串,导致SQL注入
  • 参数构造: 传入的 params 是一个JSON对象,需要在其内部嵌套一个键值对来传递恶意的SQL语句。
  • 数据库差异: 原文作者提及,针对 Oracle 数据库的注入利用可能更具挑战性。

3.4 XXE漏洞 (XML外部实体注入)

漏洞点: com.artery.richclient.RichClientService#openForm

  • 漏洞方法: openForm
  • 参数: 可从外部接收一个XML格式的参数。
  • 漏洞成因: 该方法没有有效的鉴权(isAccessible 缺失或为true),并且直接解析外部传入的XML数据,未禁用外部实体引用,导致XXE漏洞。
  • 利用方式: 构造恶意XML内容,通过 content 参数传入,可以读取服务器文件、发起内网请求等。
<!-- 示例POC结构 -->
<!DOCTYPE test [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<content>
  <someTag>&xxe;</someTag>
</content>

3.5 敏感信息泄露漏洞

漏洞点: com.artery.portal.LoginServlet

  • 漏洞成因: 该Servlet在处理请求时,通过可控的 entid 参数,与 op 参数配合触发异常后,使用 getRequestDispatcher(entid).forward(request, response) 进行内部转发
  • 利用方式: 通过构造特定的 entid 参数(如 ../../WEB-INF/web.xml),可以利用内部转发机制读取Web目录下的敏感配置文件。需要确保 op 参数能触发异常处理流程。

四、 审计方法论总结

  1. 定位入口: 首先锁定系统的核心调度器 FormService,理解其反射调用和鉴权 (isAccessible) 机制。
  2. 寻找“无鉴权”的Public方法: 全局搜索不包含 isAccessible 方法的 public 方法,这些是潜在的未授权访问入口。
  3. 数据流分析: 对找到的方法进行数据流跟踪,分析其参数是否用户可控,并最终流入危险的“Sink点”(如文件操作、数据库执行、XML解析、命令执行等)。
  4. 参数构造: 明确漏洞点的参数如何通过 FormServicecontent 参数进行传递(XML或JSON格式),并正确设置 Content-Type 头。
  5. 不要忽视后台漏洞: 本文重点在于前台漏洞挖掘,但该系统同样存在大量后台SQL注入等高危漏洞,审计时不应忽略。

五、 补充与说明

  • 原文作者提到还存在其他漏洞,如“任意文件压缩”等,因危害相对较低或属于后台漏洞未在本文详细展开。
  • 对于文中提到的漏洞,其具体POC(Proof of Concept)因涉及敏感细节未完全公开。安全研究人员可根据描述的漏洞位置、成因和参数构造方法,自行构造验证 payload。
  • 审计此类自研框架,关键在于理解其自定义的通信和鉴权机制,而非局限于传统的Spring MVC等标准框架的审计思路。

免责声明: 本文档仅用于安全技术研究和教学目的,请勿用于任何非法活动。任何个人或组织利用本文所述内容造成的任何直接或间接后果,由使用者自行承担。

某自研ERP系统Java源码安全审计与漏洞挖掘实战教学文档 文档说明 本文档基于安全研究人员“FyW06nIyAt”对某自研Java ERP系统的源码审计实战记录整理而成。旨在系统性地讲解该框架的特点、核心机制,并详细剖析其中存在的安全漏洞,为安全研究人员、开发人员及初学者提供一份详尽的代码审计实战指南。本文档遵循“ 关键点不遗漏 ”的原则,专注于技术细节与漏洞成因。 一、 系统与框架概览 1.1 基本特征 技术栈 : Java Web项目。 数据库 : 通常使用 Oracle 或 MS SQL Server。 鉴权方式 : 基于 Session 的访问控制。 核心特点 : 采用 自研框架 ,其最大特色在于通过一个名为 FormService 的中央Servlet,利用 反射机制 动态调用后端服务方法,实现前后端功能点的灵活交互。 1.2 关键指纹与鉴权方式 系统通过一个名为 PortalFilter 的过滤器对访问进行初步控制。 受控后缀 : 对包含 .jsp , .do , .action , .ajax 等特定后缀的URL请求进行拦截。 鉴权逻辑 : 过滤器检查用户Session是否存在。若Session不存在且请求的URL包含上述受控后缀,则抛出异常并重定向到登录页面。 审计启示 : 此鉴权仅针对 明确定义的路由后缀 。许多通过反射机制调用的后台功能点并未直接关联这些后缀,因此可能绕过此过滤器的基础鉴权,这是审计中需要重点关注的方向。 二、 核心机制:反射调用与鉴权 ( FormService ) com.artery.form.FormService 是整个系统审计的 核心入口 ,它本质上是一个Servlet。 2.1 核心功能 负责接收前端所有与表单相关的请求,通过解析参数,使用 反射(Reflection) 动态定位并调用后端对应的Java类和方法,最终将执行结果以XML格式返回给前端。它是连接前端请求与后端业务逻辑的“ 中间层 ”或“ API网关 ”。 2.2 调用流程与分析 读取配置 : 从 plugins.xml 等配置文件中读取服务映射关系。 解析服务名 : 从前端传入的 service 参数中解析出需要调用的 服务组(Group) 和 方法名(Method) 。 反射获取方法 : 通过 Class.getMethod() 等方法,根据解析出的类名和方法名,获取目标 Method 对象。 参数处理 : 确定目标方法的参数类型。前端数据主要通过 content 参数传入,系统会根据 Content-Type 头(如 application/xml 或 application/json )来解析 content 的内容并转换为方法所需的参数对象。 方法缓存 : 会将反射获取到的 Method 对象缓存到Map中,提升后续调用效率。 2.3 关键鉴权机制 ( isAccessible ) 这是审计 前台漏洞 的黄金法则。 在通过反射调用目标方法前,系统会尝试检查该方法是否定义了一个名为 isAccessible 的方法。 isAccessible() 方法的作用是 判断当前请求是否有权限访问该功能 。如果该方法返回 true 或存在某些允许的逻辑,则允许匿名访问。 漏洞利用前提 : 只要找到一个 不存在 isAccessible 方法 或者 isAccessible 方法逻辑存在缺陷的 public 方法,且该方法本身含有安全风险(Sink点),就可能实现 未授权访问 。 三、 漏洞详解与复现分析 以下漏洞均基于绕过 FormService 的鉴权机制进行利用。 3.1 任意文件上传漏洞 漏洞点一: com.artery.util.ServletUpload 漏洞方法 : 该类的文件上传方法。 技术细节 : 使用 DiskFileItemFactory 处理文件上传。 漏洞成因 : 上传文件时,会调用 bbswriteFileItem() 方法,该方法继续调用 bbsregisterAttachment() 。在此方法中,系统为上传的文件生成一个文件名后, 未对文件后缀名进行任何校验或过滤 ,直接将文件内容写入磁盘。 利用方式 : 通过 FormService 构造请求,调用该上传功能,上传恶意文件(如 .jsp 木马)。 漏洞点二: com.qy960.service.BBSService#phoneUpload 漏洞方法 : phoneUpload 方法。 技术细节 : 同样使用 DiskFileItemFactory 。 漏洞成因 : 与漏洞点一类似,最终也调用了未做后缀校验的 bbswriteFileItem() 方法。 利用特点 : 该方法返回的是上传后的文件名,但上传路径( path )可能不易直接获取,需要结合其他漏洞(如目录遍历读取)或进行路径爆破。 3.2 任意文件读取/目录遍历漏洞 漏洞点: com.artery.form.services.FormStudioUpdater#getStudioFile 漏洞方法 : getStudioFile 。 参数 : 接收 fileStr 参数,该参数直接用于文件路径拼接。 漏洞成因 : 方法内部未对 fileStr 参数中的 ../ 等序列进行过滤,导致 目录遍历 ,可以读取服务器上的任意文件(如 ../../../../etc/passwd )。 数据传输 : 由于通过 FormService 调用,参数需通过 content 参数以特定格式(如XML)传入。 请求构造建议 : 由于传输的是XML格式数据,将请求的 Content-Type 设置为 application/xml 并构造相应的XML payload是最佳方式。 3.3 SQL注入漏洞 (前台) 漏洞点: com.artery.workflow.ServiceImpl#sqlResult 漏洞方法 : sqlResult 。 参数 : 接收外部传入的 sql 参数。 漏洞成因 : 方法内部直接将可控的 sql 参数传入 getFieldValue() 方法中,该方法最终会执行这个SQL字符串,导致 SQL注入 。 参数构造 : 传入的 params 是一个JSON对象,需要在其内部嵌套一个键值对来传递恶意的SQL语句。 数据库差异 : 原文作者提及,针对 Oracle 数据库的注入利用可能更具挑战性。 3.4 XXE漏洞 (XML外部实体注入) 漏洞点: com.artery.richclient.RichClientService#openForm 漏洞方法 : openForm 。 参数 : 可从外部接收一个XML格式的参数。 漏洞成因 : 该方法没有有效的鉴权( isAccessible 缺失或为true),并且直接解析外部传入的XML数据, 未禁用外部实体引用 ,导致XXE漏洞。 利用方式 : 构造恶意XML内容,通过 content 参数传入,可以读取服务器文件、发起内网请求等。 3.5 敏感信息泄露漏洞 漏洞点: com.artery.portal.LoginServlet 漏洞成因 : 该Servlet在处理请求时,通过可控的 entid 参数,与 op 参数配合触发异常后,使用 getRequestDispatcher(entid).forward(request, response) 进行 内部转发 。 利用方式 : 通过构造特定的 entid 参数(如 ../../WEB-INF/web.xml ),可以利用内部转发机制读取Web目录下的敏感配置文件。需要确保 op 参数能触发异常处理流程。 四、 审计方法论总结 定位入口 : 首先锁定系统的核心调度器 FormService ,理解其反射调用和鉴权 ( isAccessible ) 机制。 寻找“无鉴权”的Public方法 : 全局搜索不包含 isAccessible 方法的 public 方法,这些是潜在的未授权访问入口。 数据流分析 : 对找到的方法进行数据流跟踪,分析其参数是否用户可控,并最终流入危险的“Sink点”(如文件操作、数据库执行、XML解析、命令执行等)。 参数构造 : 明确漏洞点的参数如何通过 FormService 的 content 参数进行传递(XML或JSON格式),并正确设置 Content-Type 头。 不要忽视后台漏洞 : 本文重点在于前台漏洞挖掘,但该系统同样存在大量后台SQL注入等高危漏洞,审计时不应忽略。 五、 补充与说明 原文作者提到还存在其他漏洞,如“ 任意文件压缩 ”等,因危害相对较低或属于后台漏洞未在本文详细展开。 对于文中提到的漏洞,其具体POC(Proof of Concept)因涉及敏感细节未完全公开。安全研究人员可根据描述的漏洞位置、成因和参数构造方法,自行构造验证 payload。 审计此类自研框架,关键在于理解其 自定义的通信和鉴权机制 ,而非局限于传统的Spring MVC等标准框架的审计思路。 免责声明 : 本文档仅用于安全技术研究和教学目的,请勿用于任何非法活动。任何个人或组织利用本文所述内容造成的任何直接或间接后果,由使用者自行承担。