xxl-job子任务越权漏洞代码分析及修复代码分析(CVE-2024-42681)
字数 972 2025-08-30 06:50:35

XXL-JOB子任务越权漏洞分析及修复指南(CVE-2024-42681)

漏洞概述

XXL-JOB是一个分布式任务调度平台,在2.4.1版本中存在子任务越权漏洞。该漏洞允许普通用户通过在执行程序A上创建任务并使用子任务ID,从而执行管理员权限才能执行的执行程序B上的子任务。

漏洞原理分析

权限控制机制

XXL-JOB的权限控制主要通过两个关键方法实现:

  1. filterJobGroupByRole方法 - 用于过滤用户可查看的执行器组
public static List<XxlJobGroup> filterJobGroupByRole(HttpServletRequest request, List<XxlJobGroup> jobGroupList_all) {
    List<XxlJobGroup> jobGroupList = new ArrayList<>();
    if (jobGroupList_all != null && jobGroupList_all.size() > 0) {
        XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
        if (loginUser.getRole() == 1) { // 管理员
            jobGroupList = jobGroupList_all;
        } else {
            List<String> groupIdStrs = new ArrayList<>();
            if (loginUser.getPermission() != null && loginUser.getPermission().trim().length() > 0) {
                groupIdStrs = Arrays.asList(loginUser.getPermission().trim().split(","));
            }
            for (XxlJobGroup groupItem : jobGroupList_all) {
                if (groupIdStrs.contains(String.valueOf(groupItem.getId()))) {
                    jobGroupList.add(groupItem);
                }
            }
        }
    }
    return jobGroupList;
}
  1. validPermission方法 - 用于验证用户对特定执行器组的操作权限
public static void validPermission(HttpServletRequest request, int jobGroup) {
    XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
    if (!loginUser.validPermission(jobGroup)) {
        throw new RuntimeException(I18nUtil.getString("system_permission_limit") + "[username=" + loginUser.getUsername() + "]");
    }
}

漏洞核心问题

漏洞存在于子任务处理逻辑中,具体在com.xxl.job.admin.service.impl.XxlJobServiceImpl类的子任务ID处理代码段:

if (jobInfo.getChildJobId()!=null && jobInfo.getChildJobId().trim().length()>0) {
    String[] childJobIds = jobInfo.getChildJobId().split(",");
    for (String childJobIdItem: childJobIds) {
        if (childJobIdItem!=null && childJobIdItem.trim().length()>0 && isNumeric(childJobIdItem)) {
            XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem));
            if (childJobInfo==null) {
                return new ReturnT<String>(ReturnT.FAIL_CODE,
                        MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem));
            }
        } else {
            return new ReturnT<String>(ReturnT.FAIL_CODE,
                    MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem));
        }
    }
}

关键问题点

  1. 在添加/更新任务时,对子任务ID仅进行了存在性验证,未检查用户对子任务的权限
  2. 在执行任务时(trigger方法),仅验证了用户对主任务的权限,未验证对子任务的权限
public ReturnT<String> trigger(XxlJobUser loginUser, int jobId, String executorParam, String addressList) {
    if (loginUser == null) {
        return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("system_permission_limit"));
    }
    XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(jobId);
    if (xxlJobInfo == null) {
        return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
    }
    if (!hasPermission(loginUser, xxlJobInfo.getJobGroup())) {
        return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("system_permission_limit"));
    }
    JobTriggerPoolHelper.trigger(jobId, TriggerTypeEnum.MANUAL, -1, null, executorParam, addressList);
    return ReturnT.SUCCESS;
}

漏洞利用场景

假设:

  • 普通用户A只有对执行器组1的权限
  • 执行器组2中存在子任务ID为2的任务

利用步骤:

  1. 用户A在组1中创建任务
  2. 在子任务ID字段中填写"2"
  3. 系统仅验证子任务ID=2是否存在,未验证用户权限
  4. 执行任务时,系统仅验证用户对组1的权限
  5. 最终同时执行了组1的任务和组2的子任务2,实现越权

修复方案

官方修复方案主要做了以下改进:

  1. addupdate接口中添加LoginUser参数,用于获取当前用户信息
  2. 在子任务验证过程中添加权限检查:
// 伪代码示例
if (!hasPermission(loginUser, childJobInfo.getJobGroup())) {
    return new ReturnT<String>(ReturnT.FAIL_CODE, "No permission for child job");
}

修复验证

验证修复是否有效的方法:

  1. 普通用户尝试添加不属于其权限范围内的子任务ID
  2. 系统应返回权限不足的错误提示
  3. 确保执行任务时也会验证用户对子任务的权限

安全建议

  1. 及时升级到修复漏洞的XXL-JOB版本
  2. 对于无法立即升级的系统,可考虑以下临时措施:
    • 自定义拦截器检查子任务权限
    • 限制普通用户创建包含子任务的任务
  3. 定期审计系统中的权限控制逻辑
  4. 实施最小权限原则,严格控制用户权限范围

总结

该漏洞暴露了XXL-JOB在子任务权限控制方面的不足,提醒开发者在设计类似功能时:

  1. 必须对所有涉及资源访问的操作进行权限验证
  2. 特别注意级联操作(如子任务)的权限控制
  3. 实施完整的权限验证链条,不遗漏任何环节
XXL-JOB子任务越权漏洞分析及修复指南(CVE-2024-42681) 漏洞概述 XXL-JOB是一个分布式任务调度平台,在2.4.1版本中存在子任务越权漏洞。该漏洞允许普通用户通过在执行程序A上创建任务并使用子任务ID,从而执行管理员权限才能执行的执行程序B上的子任务。 漏洞原理分析 权限控制机制 XXL-JOB的权限控制主要通过两个关键方法实现: filterJobGroupByRole 方法 - 用于过滤用户可查看的执行器组 validPermission 方法 - 用于验证用户对特定执行器组的操作权限 漏洞核心问题 漏洞存在于子任务处理逻辑中,具体在 com.xxl.job.admin.service.impl.XxlJobServiceImpl 类的子任务ID处理代码段: 关键问题点 : 在添加/更新任务时,对子任务ID仅进行了存在性验证,未检查用户对子任务的权限 在执行任务时( trigger 方法),仅验证了用户对主任务的权限,未验证对子任务的权限 漏洞利用场景 假设: 普通用户A只有对执行器组1的权限 执行器组2中存在子任务ID为2的任务 利用步骤: 用户A在组1中创建任务 在子任务ID字段中填写"2" 系统仅验证子任务ID=2是否存在,未验证用户权限 执行任务时,系统仅验证用户对组1的权限 最终同时执行了组1的任务和组2的子任务2,实现越权 修复方案 官方修复方案主要做了以下改进: 在 add 和 update 接口中添加 LoginUser 参数,用于获取当前用户信息 在子任务验证过程中添加权限检查: 修复验证 验证修复是否有效的方法: 普通用户尝试添加不属于其权限范围内的子任务ID 系统应返回权限不足的错误提示 确保执行任务时也会验证用户对子任务的权限 安全建议 及时升级到修复漏洞的XXL-JOB版本 对于无法立即升级的系统,可考虑以下临时措施: 自定义拦截器检查子任务权限 限制普通用户创建包含子任务的任务 定期审计系统中的权限控制逻辑 实施最小权限原则,严格控制用户权限范围 总结 该漏洞暴露了XXL-JOB在子任务权限控制方面的不足,提醒开发者在设计类似功能时: 必须对所有涉及资源访问的操作进行权限验证 特别注意级联操作(如子任务)的权限控制 实施完整的权限验证链条,不遗漏任何环节