作者:Lucifaer
博客:https://www.lucifaer.com

這篇分析其實在上周五也就是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 整體觸發流程

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中如何做的路由解析:

img

org.sonatype.nexus.bootstrap.osgi.DelegatingFilter攔截了所有的請求,大概率為動態路由加載,動態路由加載需要配置相應的Module模塊用代碼將配置與路由進行綁定并顯式加載servlet,而該漏洞的入口就在org.sonatype.nexus.extdirect.internal.ExtDirectModule#configure中:

img

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

img

繼續向下更進看到處理post請求的部分:

img

在這里我們跟進看一下如何對json格式的請求進行處理:

img

img

首先對json的語法樹進行解析,將數據提取出來:

img

可以看到需要5個變量分別為actionmethodtidtypedata

注意到isBatched是由參數長度決定的,而返回的一個數組,其長度為1,所以isBatchedfalse。之后就是傳入processIndividualRequestsInThisThread方法中:

img

在這里構造返回的結果,可以看到這里在有一個json反序列化的過程,這里主要是將返回結果以json格式返回。

2.2 jexl表達式執行

從post包的解析中可以得知我們需要構造5個參數,同時當我們構造好actionmethod后,可以直接動態調用相應的類與方法。

這個漏洞出現在org.sonatype.nexus.coreui.ComponentComponent#previewAssets:

img

首先將post包中repositoryNameexpressiontype的值取出來,這三個參數分別代表已經存在的repository的名字、expression的類型,以及表達式。

著重看一下jexl的處理過程:

img

img

注意到這里只是實例化了一個JexlSelector對象,而并沒有調用evaluate來執行表達式,所以漏洞的觸發點在其他的位置。而真正的表達式執行點在browseService.previewAssets的處理過程中,這一點也是這個漏洞最為難找的一個點。

跟進previewAssets的實現,在org.sonatype.nexus.repository.browse.internal.BrowseServiceImpl#previewAssets

img

在這里可以看到表達式最后會被當做參數形成SQL查詢,最后由OrientDb執行:

img

但是OrientDb本身是沒有contentExpression這個方法的,也就是說明這個方法是用Java來實現的,找了一下,在org.sonatype.nexus.repository.selector.internal.ContentExpressionFunction

img

checkJexlExpression中:

img

調用了selectorManage.evaluate來執行jexl表達式:

img

0x03 構造POC

通過上面的分析,我們只需要按照post包解析中的參數進行相應的構造即可,下面為一個例子:

img

注意,這個漏洞需要當Nexus中存在已有的jar包,在本地驗證的時候先傳一個jar報上去。至于原理分析可能后面會單獨再拿出來分析。

0x04 Reference


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/827/