0x00、前言
Apache-Solr-RCE(CNVD-2023-27598)复现与分析,核心跟着原作者分析文章进行复现和过程调试。
0x01、漏洞描述
Apache Solr是一个开源搜索服务引擎,Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现。
在Apache Solr 受影响版本中,由于Solr默认配置下存在服务端请求伪造漏洞,且SolrResourceLoader中实现了java SPI机制。当Solr以SolrCloud模式启动时,攻击者可以通过构造恶意的solrconfig.xml文件,组合利用从而执行任意java代码。
0x02、漏洞范围
8.10.0 <= Apache Solr < 9.2.0
0x03、环境搭建
github源码:https://github.com/apache/solr/tags
(8系列使用ant ivy-bootstrap、ant idea构建导入idea即可、9系列使用gradle构建编译导入idea)
官方solr程序安装包,src后缀为源码,下载不带src后缀的即为编译好的程序运行包:
https://dlcdn.apache.org/lucene/solr/
运行方式:
进入安装包bin目录下
solr.cmd start -c -f -a "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:35005"
-c开启solrcloud模式,-f后台显示执行情况,-a调试参数(端口设置同idea一样)
将源码导入idea,开启远程调试就可以进行断点调试
0x04、漏洞复现
通过configset添加主题,name参数对应主题名,可自取
curl -X POST --header "Content-Type:application/octet-stream" --data-binary @conf.zip "http://ip:8983/solr/admin/configs?action=UPLOAD&name=lib9"
其中上传的压缩包可将默认配置进行打包成zip进行上传
伪造恶意jar包(注意依赖必须添加程序包中的lucene-codecs-8.11.2.jar、lucene-core-8.11.2.jar两个依赖包)
通过Idea添加控件生成恶意jar包
复制默认配置中的solrconfig.xml,修改solrconfig.xml文件,将恶意lib植入xml文件中
主机开启unc,将恶意jar放入路径中
修改主体solrconfig配置文件,name对应上传的主体名
curl -X POST --header "Content-Type:application/octet-stream" --data-binary @solrconfig.xml "http://192.168.43.233:8983/solr/admin/configs?action=UPLOAD&name=lib9&filePath=solrconfig.xml&overwrite=true"
上传完solrconfig.xml文件覆盖后,再新建主题
触发漏洞
0x05、原理分析
根据原作者分析思路,在通过configset上传主题时,将默认的demo进行上传,其中demo中自带了solrconfig.xml文件,创建后可直接创建主题
其中调试SchemaDesignerConfigSetHelper.loadSolrConfig
方法创建solr资源加载器过后,读取资源会传入SOLR_CONFIG_XML
获取的solrconfig.xml文件
跟进到SolrConfig.readFromResourceLoader
方法,调用构造方法
从方法注释可以知道该构造方法是从资源加载器、配置名称和流创建配置实例
其中会创建资源提供器,其中会对solrconfig.xml文件从资源配置中获取
由于上传的默认配置中包含了默认的solrconfig.xml文件,因此能够在zookeeper中找到配置文件,如果上传的主题配置中删除了solrconfig.xml,则会抛出异常提示找不到solrconfig.xml文件
资源加载器创建好后,进入主要的initLibs
方法初始化lib资源,由于默认配置中的solrconfig.xml中的lib标签未添加额外的,因此读取添加到加载器的步骤都会跳过。
因此重新覆盖solrconfig.xml文件,将恶意jar路径通过unc路径方式(windows环境下,并且将该目录的文件共享打开,使服务器能访问该主机)放置恶意solrconfig.xml中
curl -X POST --header "Content-Type:application/octet-stream" --data-binary @solrconfig.xml "http://192.168.43.233:8983/solr/admin/configs?action=UPLOAD&name=lib12&filePath=solrconfig.xml&overwrite=true" |
上传后重新新建主题
此时initlibs
获取到solrconfig.xml
文件中的lib
标签
再通过getFilteredURLs.getURLs
方法去循环获取lib
标签中的url
值,获取url
过程:
获取到url后,添加到url类加载器中
添加到加载器过后,调用reloadLuceneSPI
方法进行重载SPI操作
加载PostingsFormats
调用到NamedSPILoader.reload
方法进行重载
先是获取SPI类迭代器,关联的类名为org.apache.lucene.codecs.PostingsFormat
接着从迭代加载器中获取/META-INF/services/org.apache.lucene.codecs.PostingsFormat
文件名
写入到URL连接流中
再循环读取/META-INF/services/org.apache.lucene.codecs.PostingsFormat
文件中的类名,添加到linesIterator
中
然后循环进行实例化操作
最后循环获取到构造恶意jar中/META-INF/services/org.apache.lucene.codecs.PostingsFormat
文件名下的恶意类名路径
随后进行实例化恶意类调用静态方法触发漏洞
0x06、漏洞修复
官方更新补丁,升级至9.2.0版本:https://solr.apache.org/downloads.html