通过审计cms来掌握CodeQL的使用
字数 2174 2025-08-10 12:17:54

通过审计CMS掌握CodeQL的使用 - 华夏ERP代码审计实战指南

一、环境搭建

1.1 目标系统准备

  • 目标系统: 华夏ERP v2.3
  • 源码地址: https://github.com/jishenghua/jshERP/tree/v2.3
  • 数据库准备:
    • 创建数据库: jsh_erp
    • 导入SQL文件: docs/jsh_erp.sql
  • 运行环境:
    • 主启动类: src\main\java\com\jsh\erp\ErpApplication.java
  • 默认凭证:
    • 用户名: jsh
    • 密码: 123456

1.2 开发环境配置

  • 使用IDEA导入项目并自动加载依赖
  • 确保Maven依赖正确解析

二、第三方组件扫描

2.1 使用PomEye进行组件扫描

  • 工具介绍: PomEye是作者开发的Maven依赖分析工具
  • 下载地址: https://github.com/feiweiliang/PomEye
  • 关键发现: 存在漏洞版本的fastjson组件

2.2 CodeQL审计目标

  • 定位fastjson的parseparseObject方法调用点
  • 确认参数是否可控

三、系统架构分析

3.1 关键包结构分析

包名 功能描述 重要类/方法
config 系统配置 Swagger配置、Mapper路径配置、分页拦截器
constants 常量定义 SERVICE_SUCCESS_CODE = 200USER_IS_MANAGER = 0
filter 过滤器 用户登录校验过滤器
controller 业务控制器 多个功能控制器
exception 自定义异常 调试辅助
utils 工具类 各种辅助工具

3.2 关键控制器分析

  1. AccountController

    • findBySelect: 查找下拉框中所有账户ID和用户名
    • getAccount: 获取所有账户
    • findAccountInOutList: 查找主表出入库涉及的账户
    • updateAmountIsDefault: 更新默认账户
  2. DepotController

    • 仓库操作相关功能
  3. FunctionController

    • 用户功能权限管理
  4. InOutItemController

    • findBySelect: 查找收支项目
    • deleteInOutItem: 删除收支项目
  5. UserController

    • resetPwd: 密码重置
    • deleteUser: 用户删除
    • getUserList: 获取用户列表
    • 登录/登出功能
  6. SystemConfigController

    • deleteConfig: 删除系统配置
  7. SupplierController

    • updateAdvanceIn: 更新供应商预付款
    • findBySelect: 查找客户/供应商信息
    • 导入导出功能

四、白盒审计发现

4.1 越权漏洞

4.1.1 任意密码重置

位置: UserController.resetPwd

@PostMapping(value = "/resetPwd")
public String resetPwd(@RequestParam("id") Long id, 
                      HttpServletRequest request) throws Exception {
    Map<String, Object> objectMap = new HashMap<String, Object>();
    String password = "123456"; // 硬编码密码
    String md5Pwd = Tools.md5Encryp(password);
    int update = userService.resetPwd(md5Pwd, id);
}

问题:

  • 无权限验证
  • 密码硬编码为"123456"
  • 仅需用户ID即可重置任意用户密码

4.1.2 任意用户删除

位置: UserController.deleteUser

@PostMapping("/deleteUser")
@ResponseBody
public Object deleteUser(@RequestParam("ids") String ids)throws Exception{
    JSONObject result = ExceptionConstants.standardSuccess();
    userService.batDeleteUser(ids); // 批量删除用户
    return result;
}

问题:

  • 无权限验证
  • 可批量删除任意用户

4.2 信息泄露漏洞

位置: UserController.getUserList

@GetMapping(value = "/getUserList")
public JSONArray getUserList(HttpServletRequest request)throws Exception {
    JSONArray dataArray = new JSONArray();
    try {
        List<User> dataList = userService.getUser();
        if (null != dataList) {
            for (User user : dataList) {
                JSONObject item = new JSONObject();
                item.put("id", user.getId());
                item.put("userName", user.getUsername());
                dataArray.add(item)
        }catch(Exception e){
            e.printStackTrace();
        }
    return dataArray;
}

问题:

  • 无权限验证
  • 泄露所有用户ID和用户名信息

4.3 鉴权绕过漏洞

位置: LogCostFilter.doFilter

String requestUrl = servletRequest.getRequestURI();
if (requestUrl != null && 
    (requestUrl.contains("/doc.html") || 
     requestUrl.contains("/register.html") || 
     requestUrl.contains("/login.html"))) {
    chain.doFilter(request, response);
    return;
}

绕过方式:

  1. 路径遍历绕过:
    • /register.html/../../user/getUserList
  2. 静态资源后缀绕过:
    • 过滤器配置忽略.css, .js, .jpg, .png等静态资源
    • 可尝试添加后缀如/user/getUserList.css

五、CodeQL审计实践

5.1 创建CodeQL数据库

codeql database create --language=java --source-root=jshERP erp-db

5.2 编写查询规则

5.2.1 查找fastjson调用点

import java

from MethodAccess call, Method method
where 
  method.getDeclaringType().hasQualifiedName("com.alibaba.fastjson", "JSON") and
  (method.getName() = "parse" or method.getName() = "parseObject") and
  call.getMethod() = method
select call, "Potential fastjson deserialization vulnerability"

5.2.2 查找无权限检查的控制器方法

import java

from Class c, Method m
where
  c.getAnAnnotation().toString() = "@RestController" and
  m.getDeclaringType() = c and
  not exists(MethodAccess ma | 
    ma.getMethod().getName() = "checkLogin" and
    ma.getEnclosingCallable() = m
  )
select m, "Controller method without login check"

5.2.3 查找硬编码密码

import java

from Variable v, StringLiteral s
where
  v.getInitializer() = s and
  s.toString().matches("%123456%")
select s, "Hardcoded password found"

5.3 分析结果处理

  • 验证每个发现的调用点是否确实存在安全问题
  • 跟踪数据流确认参数是否可控
  • 结合业务逻辑评估实际影响

六、修复建议

6.1 越权漏洞修复

  1. 添加权限验证注解:
@PreAuthorize("hasRole('ADMIN')")
@PostMapping(value = "/resetPwd")
public String resetPwd(...) { ... }
  1. 实现权限检查逻辑:
User currentUser = getCurrentUser();
if(!currentUser.isAdmin() && !currentUser.getId().equals(id)) {
    throw new AccessDeniedException();
}

6.2 信息泄露修复

  1. 添加权限控制:
@GetMapping(value = "/getUserList")
@PreAuthorize("isAuthenticated()")
public JSONArray getUserList(...) { ... }
  1. 实施数据脱敏:
item.put("userName", maskUsername(user.getUsername()));

6.3 鉴权绕过修复

  1. 改进路径检查逻辑:
String normalizedPath = Paths.get(requestUrl).normalize().toString();
if(normalizedPath.equals("/register.html") || ...) {
    ...
}
  1. 严格限制静态资源访问:
@WebFilter(urlPatterns = {"/static/*"})

七、总结

本次审计通过CodeQL结合手动分析,发现了华夏ERP系统中的多个安全问题,包括:

  1. 多处越权操作(密码重置、用户删除)
  2. 敏感信息泄露
  3. 鉴权绕过漏洞
  4. 第三方组件风险

CodeQL在此次审计中发挥了重要作用,特别是在:

  • 快速定位特定API调用点(fastjson)
  • 识别缺少安全检查的方法
  • 发现硬编码凭证等不良实践

建议开发团队:

  1. 实施严格的权限验证机制
  2. 修复已知的fastjson漏洞
  3. 改进过滤器的路径检查逻辑
  4. 定期进行代码安全审计
通过审计CMS掌握CodeQL的使用 - 华夏ERP代码审计实战指南 一、环境搭建 1.1 目标系统准备 目标系统 : 华夏ERP v2.3 源码地址 : https://github.com/jishenghua/jshERP/tree/v2.3 数据库准备 : 创建数据库: jsh_erp 导入SQL文件: docs/jsh_erp.sql 运行环境 : 主启动类: src\main\java\com\jsh\erp\ErpApplication.java 默认凭证 : 用户名: jsh 密码: 123456 1.2 开发环境配置 使用IDEA导入项目并自动加载依赖 确保Maven依赖正确解析 二、第三方组件扫描 2.1 使用PomEye进行组件扫描 工具介绍 : PomEye是作者开发的Maven依赖分析工具 下载地址 : https://github.com/feiweiliang/PomEye 关键发现 : 存在漏洞版本的fastjson组件 2.2 CodeQL审计目标 定位fastjson的 parse 或 parseObject 方法调用点 确认参数是否可控 三、系统架构分析 3.1 关键包结构分析 | 包名 | 功能描述 | 重要类/方法 | |------|----------|-------------| | config | 系统配置 | Swagger配置、Mapper路径配置、分页拦截器 | | constants | 常量定义 | SERVICE_SUCCESS_CODE = 200 、 USER_IS_MANAGER = 0 | | filter | 过滤器 | 用户登录校验过滤器 | | controller | 业务控制器 | 多个功能控制器 | | exception | 自定义异常 | 调试辅助 | | utils | 工具类 | 各种辅助工具 | 3.2 关键控制器分析 AccountController findBySelect : 查找下拉框中所有账户ID和用户名 getAccount : 获取所有账户 findAccountInOutList : 查找主表出入库涉及的账户 updateAmountIsDefault : 更新默认账户 DepotController 仓库操作相关功能 FunctionController 用户功能权限管理 InOutItemController findBySelect : 查找收支项目 deleteInOutItem : 删除收支项目 UserController resetPwd : 密码重置 deleteUser : 用户删除 getUserList : 获取用户列表 登录/登出功能 SystemConfigController deleteConfig : 删除系统配置 SupplierController updateAdvanceIn : 更新供应商预付款 findBySelect : 查找客户/供应商信息 导入导出功能 四、白盒审计发现 4.1 越权漏洞 4.1.1 任意密码重置 位置 : UserController.resetPwd 问题 : 无权限验证 密码硬编码为"123456" 仅需用户ID即可重置任意用户密码 4.1.2 任意用户删除 位置 : UserController.deleteUser 问题 : 无权限验证 可批量删除任意用户 4.2 信息泄露漏洞 位置 : UserController.getUserList 问题 : 无权限验证 泄露所有用户ID和用户名信息 4.3 鉴权绕过漏洞 位置 : LogCostFilter.doFilter 绕过方式 : 路径遍历绕过: /register.html/../../user/getUserList 静态资源后缀绕过: 过滤器配置忽略 .css , .js , .jpg , .png 等静态资源 可尝试添加后缀如 /user/getUserList.css 五、CodeQL审计实践 5.1 创建CodeQL数据库 5.2 编写查询规则 5.2.1 查找fastjson调用点 5.2.2 查找无权限检查的控制器方法 5.2.3 查找硬编码密码 5.3 分析结果处理 验证每个发现的调用点是否确实存在安全问题 跟踪数据流确认参数是否可控 结合业务逻辑评估实际影响 六、修复建议 6.1 越权漏洞修复 添加权限验证注解: 实现权限检查逻辑: 6.2 信息泄露修复 添加权限控制: 实施数据脱敏: 6.3 鉴权绕过修复 改进路径检查逻辑: 严格限制静态资源访问: 七、总结 本次审计通过CodeQL结合手动分析,发现了华夏ERP系统中的多个安全问题,包括: 多处越权操作(密码重置、用户删除) 敏感信息泄露 鉴权绕过漏洞 第三方组件风险 CodeQL在此次审计中发挥了重要作用,特别是在: 快速定位特定API调用点(fastjson) 识别缺少安全检查的方法 发现硬编码凭证等不良实践 建议开发团队: 实施严格的权限验证机制 修复已知的fastjson漏洞 改进过滤器的路径检查逻辑 定期进行代码安全审计