作者: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:

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

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個變量分別為action、method、tid、type、data。
注意到isBatched是由參數長度決定的,而返回的一個數組,其長度為1,所以isBatched為false。之后就是傳入processIndividualRequestsInThisThread方法中:

在這里構造返回的結果,可以看到這里在有一個json反序列化的過程,這里主要是將返回結果以json格式返回。
2.2 jexl表達式執行
從post包的解析中可以得知我們需要構造5個參數,同時當我們構造好action和method后,可以直接動態調用相應的類與方法。
這個漏洞出現在org.sonatype.nexus.coreui.ComponentComponent#previewAssets:

首先將post包中repositoryName、expression、type的值取出來,這三個參數分別代表已經存在的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
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/827/
暫無評論