Nexus Repository Manager 2.x 命令注入漏洞 (CVE-2019-5475) 兩次繞過
作者: Badcode and Longofo@知道創宇404實驗室
時間: 2020年2月9日
原文連結:
英文連結:
前言
2019年9月初我們應急了Nexus Repository Manager 2.x 命令注入漏洞(CVE-2019-5475),其大致的原因和復現步驟在 上公佈了,在應急完這個漏洞之後,我們分析該漏洞的修復補丁,發現修復不完全,仍然可以繞過,本篇文章記錄該漏洞的兩次繞過。雖然早釋出了兩次的修復版本,由於官方第二次更新公告太慢 ,所以現在才發。
幾次更新時間線:
- CVE-2019-5475(2019-08-09)
- 第一次繞過,CVE-2019-15588(2019-10-28)
- 第二次繞過,未分配CVE,更新了公告影響版本(2020-3-25)
注:原始漏洞分析、第一次繞過分析、第二次繞過分析部分主要由Badcode師傅編寫,第二次繞過分析+、最新版本分析主要由Longofo新增。
原始漏洞分析
利用條件
- 需管理員許可權(預設認證:admin/admin123)
漏洞分析
以下分析的程式碼基於 2.14.9-01 版本。
漏洞點是出現在 Yum Repository 外掛中,當配置 Yum 的
createrepo
或者
mergerepo
時
程式碼層面會跳到
YumCapability
的
方法中。
在上面
Path of "createrepo"
中設定的值會透過
getConfig().getCreaterepoPath()
獲取到,獲取到該值之後,呼叫
this.validate()
方法
傳進來的
path
是使用者可控的,之後將
path
拼接
--version
之後傳遞給
commandLineExecutor.exec()
方法,看起來像是執行命令的方法,而事實也是如此。跟進
CommandLineExecutor
類的
exec
方法
在執行命令前先對命令解析,
CommandLine.parse()
,會以空格作為分隔,獲取可執行檔案及引數。
最終是呼叫了
Runtime.getRuntime().exec()
執行了命令。
例如,使用者傳入的 command 是
cmd.exe /c whoami
,最後到
getRuntime().exec()
方法就是
Runtime.getRuntime().exec({"cmd.exe","/c","whoami"})
。
所以漏洞的原理也很簡單,就是在
createrepo
或者
mergerepo
路徑設定的時候,該路徑可以由使用者指定,中途拼接了
--version
字串,最終到了
getRuntime.exec()
執行了命令。
漏洞復現
在
Path of "createrepo"
裡面傳入 payload。
在
Status
欄可以看到執行的結果
第一次繞過分析
第一次補丁分析
官方補丁改了幾個地方,關鍵點在
常規做法,在執行命令前對命令進行過濾。新增加了一個
getCleanCommand()
方法,對命令進行過濾。
allowedExecutables
是一個 HashSet,裡面只有兩個值,
createrepo
和
mergerepo
。先判斷使用者傳入的
command
是否在
allowedExecutables
裡面,如果在,直接拼接
params
即
--version
直接返回。接著對使用者傳入的
command
進行路徑判斷,如果是以nexus的工作目錄(
applicationDirectories.getWorkDirectory().getAbsolutePath()
)開頭的,直接返回 null。繼續判斷,如果檔名不在
allowedExecutables
則返回 null,也就是這條命令需要 以
/createrepo
或者
/mergerepo
結尾。都透過判斷之後,檔案的絕對路徑拼接
--version
返回。
第一次補丁繞過
說實話,看到這個補丁的第一眼,我就覺得大機率可以繞。
傳入的命令滿足兩個條件即可,不以nexus的工作目錄開頭,並且以
/createrepo
或者
/mergerepo
結尾即可。
看到補丁中的
getCleanCommand()
方法,
new File(command)
是關鍵,
new File()
是透過將給定的路徑名字串轉換為抽象路徑名來建立新的File例項。 值得注意的是,這裡面路徑字串是可以使用空格的,也就是
String f = "/etc/passwd /shadow"; File file = new File(f);
這種是合法的,並且呼叫
file.getName()
取到的值是
shadow
。結合這個特性,就可以繞過補丁裡面的判斷
String cmd = "/bin/bash -c whoami /createrepo"; File file = new File(cmd); System.out.println(file.getName()); System.out.println(file.getAbsolutePath());
執行結果
可以看到,
file.getName()
的值正是
createrepo
,滿足判斷。
第一次繞過測試
測試環境
- 2.14.14-01 版本
- Linux
測試步驟
在
Path of "createrepo"
裡面傳入 payload。
在
Status
欄檢視執行的結果
可以看到,成功繞過了補丁。
在 Windows 環境下面就麻煩點了,沒有辦法使用
cmd.exe /c whoami
這種形式執行命令了,因為
cmd.exe /c whoami
經過
new File()
之後變成了
cmd.exe \c whoami
,後面是執行不了的。可以直接執行exe,注意後面是還會拼接
--version
的,所以很多命令是執行不了的,但是還是有辦法利用能執行任意exe這點來做後續的攻擊的。
第二次繞過分析
第二次補丁分析
在我提交上述繞過方式後,官方修復了這種繞過方式,看下官方的
在
getCleanCommand()
方法中增加了一個
file.exists()
判斷檔案是否存在。之前的
/bin/bash -c whoami /createrepo
這種形式的肯定就不行了,因為這個檔案並不存在。所以現在又多了一個判斷,難度又加大了。難道就沒有辦法繞過了?不是的,還是可以繞過的。
第二次補丁繞過
現在傳入的命令要滿足三個條件了
- 不以nexus的工作目錄開頭
- 以
/createrepo
或者/mergerepo
結尾 - 並且這
createrepo
或者mergerepo
這個檔案存在
看到
file.exists()
我就想起了 php 中的
file_exists()
,以前搞 php 的時候也遇到過這種判斷。有個系統特性,在 Windows 環境下,目錄跳轉是允許跳轉不存在的目錄的,而在Linux下面是不能跳轉不存在目錄的。
測試一下
Linux
可以看到,
file.exists()
返回了 false
Windows
file.exists()
返回了 true
上面我們說了
new File(pathname)
,pathname 是允許帶空格的。在利用上面WIndows環境下的特性,把cmd設定成
C:\\Windows\\System32\\calc.exe \\..\\..\\win.ini
經過
parse()
方法,最終到
getRuntime.exec({"C:\\Windows\\System32\\calc.exe","\\..\\..\\win.ini"})
,這樣就能執行
calc
了。
在上面這個測試
win.ini
是確實存在的檔案,回到補丁上面,需要判斷
createrepo
或者
mergerepo
存在。首先從功能上來說,createrepo 命令用於建立 yum 源(軟體倉庫),即為存放於本地特定位置的眾多rpm包建立索引,描述各包所需依賴資訊,並形成後設資料。也就是這個
createrepo
在Windows下不太可能存在。如果這個不存在的話是沒有辦法經過判斷的。既然伺服器內不存在
createrepo
,那就想辦法建立一個,我首先試的是找個上傳點,嘗試上傳一個
createrepo
,但是沒找到上傳之後名字還能保持不變的點。在
Artifacts Upload
處上傳之後,都變成
Artifact-Version.Packaging
這種形式的名字了,
Artifact-Version.Packaging
這個是不滿足第二個判斷的,得以
createrepo
結尾。
一開始看到
file.exists()
就走進了思維定勢,以為是判斷檔案存在的,但是看了官方的文件,發現是判斷檔案或者目錄存在的。。這點也就是這個漏洞形成的第二個關鍵點,我不能建立檔案,但是可以建立資料夾啊。在
Artifacts Upload
上傳Artifacts 的時候,可以透過
GAV Parameters
來定義。
當
Group
設定為
test123
,
Artifact
設定為
test123
,
Version
設定成
1
,當上傳
Artifacts
的時候,是會在伺服器中建立對應的目錄的。對應的結構如下
如果我們將
Group
設定為
createrepo
,那麼就會建立對應的
createrepo
目錄。
結合兩個特性來測試一下
String cmd = "C:\\Windows\\System32\\calc.exe \\..\\..\\..\\nexus\\sonatype-work\\nexus\\storage\\thirdparty\\createrepo"; File file = new File(cmd); System.out.println(file.exists()); System.out.println(file.getName()); System.out.println(file.getAbsolutePath());
可以看到,
file.exists()
返回了true,
file.getName()
返回了
createrepo
,都符合判斷了。
最後到
getRuntime()
裡面大概就是
getRuntime.exec({"C:\Windows\System32\notepad.exe","\..\..\..\nexus\sonatype-work\nexus\storage\thirdparty\createrepo","--version"})
是可以成功執行
notepad.exe
的。(calc.exe演示看不到程式哈,所以換成Notepad.exe)
第二次繞過測試
測試環境
- 2.14.15-01 版本
- Windows
測試步驟
在
Path of "createrepo"
裡面傳入 payload。
檢視程式,
notepad.exe
啟動了
可以看到,成功繞過了補丁。
第二次繞過分析+
經過Badcode師傅第二次繞過分析,可以看到能成功在Windows系統執行命令了。但是有一個很大的限制:
- nexus需要安裝在系統盤
- 一些帶引數的命令無法使用
在上面說到的
Artifacts Upload
上傳處是可以上傳任意檔案的,並且上傳後的檔名都是透過自定義的引數拼接得到,所以都能猜到。那麼可以上傳自己編寫的任意exe檔案了。
第二次繞過分析+測試
測試環境
- 2.14.15-01 版本
- Windows
測試步驟
導航到
Views/Repositories->Repositories->3rd party->Configuration
,我們可以看到
預設本地儲存位置
的絕對路徑(之後上傳的內容也在這個目錄下):
導航到
Views/Repositories->Repositories->3rd party->Artifact Upload
,我們可以上傳惡意的exe檔案:
該exe檔案將被重新命名為
createrepo-1.exe
(自定義的引數拼接的):
同樣在
Path of "createrepo"
裡面傳入 payload(這時需要注意前面部分這時是以nexus安裝目錄開頭的,這在補丁中會判斷,所以這裡可以在最頂層加
..\
或者弄個虛假層
aaa\..\
等)
可以看到createrepo-1.exe已經執行了:
最新版本分析
最新版本補丁分析
第二次補丁繞過之後,官方又進行了修復,官方 主要如下
刪除了之前的修復方式,增加了
YumCapabilityUpdateValidator
類,在
validate
中將獲取的值與properties中設定的值使用
equals
進行絕對相等驗證。這個值要修改只能透過
sonatype-work/nexus/conf/capabilities.xml
最新版本驗證
前端直接禁止修改了,透過抓包修改測試:
在
YumCapabilityUpdateValidator.validate
斷到
可以看到這種修復方式無法再繞過了,除非有檔案覆蓋的地方覆蓋配置檔案,例如解壓覆蓋那種方式,不過沒找到。
不過
Artifacts Upload
那裡可以上傳任意檔案的地方依然還在,如果其他地方再出現上面的情況依然可以利用到。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69912109/viewspace-2701631/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Sql注入之WAF繞過SQL
- sql注入之堆疊注入及waf繞過注入SQL
- PfSense命令注入漏洞分析
- 利用反射型XSS二次注入繞過CSP form-action限制反射ORM
- 幾種通用防注入程式繞過方法
- sql注入waf繞過簡單入門SQL
- 網站漏洞檢測解析繞過上傳漏洞網站
- 檔案包含漏洞(繞過姿勢)
- 威脅快報|Nexus Repository Manager 3新漏洞已被用於挖礦木馬傳播,建議使用者儘快修復
- 4、幾種通用防注入程式繞過方法
- 檔案上傳漏洞(繞過姿勢)
- PHP命令執行與繞過PHP
- 漏洞分析 | Dubbo2.7.7反序列化漏洞繞過分析
- Cisco ASA Software遠端認證繞過漏洞
- 文字檔案上傳漏洞[任意.繞過.解析]
- Cisco接入點Web介面認證繞過漏洞Web
- XWorkParameterInterceptor類繞過安全限制漏洞-解決2
- 用友-NC-Cloud存在控制檯繞過漏洞Cloud
- Windows下cmd/powershell命令混淆繞過Windows
- 關於Ghostscript SAFER沙箱繞過漏洞的分析
- js繞過-前端加密繞過JS前端加密
- Oracle資料庫訪問限制繞過漏洞 解決Oracle資料庫
- MySQL許可權提升及安全限制繞過漏洞(轉)MySql
- 使用DLL注入繞過“受控制的資料夾訪問”功能
- 命令繞過寶塔皮膚強制登入
- 遠端下載上傳命令(繞過大小限制)
- 網站漏洞修復服務商對繞過認證漏洞的探討網站
- 2.Windows下Sonatype Nexus Repository 安裝與使用Windows
- 爬蟲兩種繞過5s盾的方法爬蟲
- 五種繞過Linux命令別名的方法Linux
- 駭客繞過防火牆利用Citrix漏洞入侵美國人口普查局防火牆
- 新iPhone漏洞,可繞過密碼訪問聯絡人和照片iPhone密碼
- 思科WebEx線上視訊會議軟體曝命令注入漏洞Web
- 警惕:網件無線路由器曝出命令注入漏洞路由器
- 4 種繞過 Linux/Unix 命令別名的方法Linux
- XML實體注入漏洞XML
- 24:WEB漏洞-檔案上傳之WAF繞過及安全修復Web
- nexus-maven-repository-index.zip手動下載與設定MavenIndex