Lucifaer's Blog.

Nexus Repository Manager 3 远程代码执行漏洞分析(CVE-2019-7238)

Word count: 1,224 / Reading time: 5 min
2019/02/19 Share

这篇分析其实在上周五也就是2月15号左右就已经分析完了,但是当时没有及时发出来,当周一看到iswin dalao发出的详尽分析后才把这篇分析发布做了预警算是慢了n步2333…

总体来说这个漏洞流程是比较好分析的,真正的难度是找漏洞触发点,当时分析的时候找了半天没找到触发点,最后还是硬着头皮在OrientDb的处理流程中绕了半天才意识到…还是太菜了

0x00 漏洞概述

Insufficient access controls have been discovered in Nexus Repository Manager 3 which allow remote code execution.

An unauthenticated user can craft requests in such a manner that can execute java code on the server. We have mitigated the issue by adding the necessary access controls as well as disabling the ability to execute arbitrary java code via this path. This advisory provides the pertinent information needed to properly address this vulnerability, along with the details on how to reach us if you have any further questions or concerns.

从官方的漏洞简述来看简单的来说就是由于未授权访问的用户可以构造请求而造成任意代码执行。而且因为3.15.0+以上的版本增加了用户认证,所以3.15.0+的版本不受此漏洞的影响。所以根据diff的结果,可以大致的确定漏洞在org.sonatype.nexus.coreui.ComponentComponent#previewAssets

-w1338

0x01 整体触发流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ExtDirectModule$configure:60 # 路由绑定与请求解析
ExtDirectServlet$doPost:155 # 处理post请求
DirectJNgineServlet$doPost:595 # 根据不同的Content-Type来解析请求
DirectJNgineServlet$processRequest:632 # 解析json请求
JsonRequestProcesor$process:119 # 解析json语法树
JsonRequestProcessor$getIndividualJsonRequests:216 # 提取json数据
JsonRequestProcesor$process:133 # 构造返回结构
ComponentComponent$previewAssets:188 # 解析post包中的data数据并构造查询语句查询包
ComponentComponent$previewAssets:208 # 获得查询结果
BrowseServiceImpl$previewAssets:252 # 构建OrientDb查询语句
BrowseServiceImpl$previewAssets:258 # 拼接查询语句
BrowseServiceImpl$previewAssets:262 # 执行查询
MetadataNodeEntityAdapter$countByQuery:221 # 执行OrientDb查询语句
ContextExpressionFunction$execute:125 # 提取jexl表达式
ContextExpressionFunction$checkJexlExpression:154 # 执行jexl表达式

0x02 漏洞分析

漏洞的触发主要分两部分:post包解析及jexl表达式执行。

2.1 post包解析

首先先看一下web.xml中如何做的路由解析:

org.sonatype.nexus.bootstrap.osgi.DelegatingFilter拦截了所有的请求,大概率为动态路由加载,动态路由加载需要配置相应的Module模块用代码将配置与路由进行绑定并显式加载servlet,而该漏洞的入口就在org.sonatype.nexus.extdirect.internal.ExtDirectModule#configure中:

直接跟进org.sonatype.nexus.extdirect.internal.ExtDirectServlet$doPost:

继续向下更进看到处理post请求的部分:

在这里我们跟进看一下如何对json格式的请求进行处理:

首先对json的语法树进行解析,将数据提取出来:

可以看到需要5个变量分别为actionmethodtidtypedata

注意到isBatched是由参数长度决定的,而返回的一个数组,其长度为1,所以isBatchedfalse。之后就是传入processIndividualRequestsInThisThread方法中:

在这里构造返回的结果,可以看到这里在有一个json反序列化的过程,这里主要是将返回结果以json格式返回。

2.2 jexl表达式执行

从post包的解析中可以得知我们需要构造5个参数,同时当我们构造好actionmethod后,可以直接动态调用相应的类与方法。

这个漏洞出现在org.sonatype.nexus.coreui.ComponentComponent#previewAssets:

首先将post包中repositoryNameexpressiontype的值取出来,这三个参数分别代表已经存在的repository的名字、expression的类型,以及表达式。

着重看一下jexl的处理过程:

注意到这里只是实例化了一个JexlSelector对象,而并没有调用evaluate来执行表达式,所以漏洞的触发点在其他的位置。而真正的表达式执行点在browseService.previewAssets的处理过程中,这一点也是这个漏洞最为难找的一个点。

跟进previewAssets的实现,在org.sonatype.nexus.repository.browse.internal.BrowseServiceImpl#previewAssets

在这里可以看到表达式最后会被当做参数形成SQL查询,最后由OrientDb执行:

但是OrientDb本身是没有contentExpression这个方法的,也就是说明这个方法是用Java来实现的,找了一下,在org.sonatype.nexus.repository.selector.internal.ContentExpressionFunction

checkJexlExpression中:

调用了selectorManage.evaluate来执行jexl表达式:

0x03 构造POC

通过上面的分析,我们只需要按照post包解析中的参数进行相应的构造即可,下面为一个例子:

注意,这个漏洞需要当Nexus中存在已有的jar包,在本地验证的时候先传一个jar报上去。至于原理分析可能后面会单独再拿出来分析。

0x04 Reference

CATALOG
  1. 1. 0x00 漏洞概述
  2. 2. 0x01 整体触发流程
  3. 3. 0x02 漏洞分析
    1. 3.1. 2.1 post包解析
    2. 3.2. 2.2 jexl表达式执行
  4. 4. 0x03 构造POC
  5. 5. 0x04 Reference