0x01.技術(shù)文章僅供參考學(xué)習(xí),請(qǐng)勿使用本文中所提供的任何技術(shù)信息或代碼工具進(jìn)行非法測(cè)試和違法行為。若使用者利用本文中技術(shù)信息或代碼工具對(duì)任何計(jì)算機(jī)系統(tǒng)造成的任何直接或者間接的后果及損失,均由使用者本人負(fù)責(zé)。本文所提供的技術(shù)信息或代碼工具僅供于學(xué)習(xí),一切不良后果與文章作者無(wú)關(guān)。使用者應(yīng)該遵守法律法規(guī),并尊重他人的合法權(quán)益。藍(lán)凌EKP由深圳市藍(lán)凌軟件股份有限公司自主研發(fā),是一款全程在線數(shù)字化OA,應(yīng)用于大中型企業(yè)在線化辦公,包含流程管理、知識(shí)管理、會(huì)議管理、公文管理等等。藍(lán)凌0A的thirdImSyncForKKWebService接口存在任意文件讀取漏洞。攻擊者可利用漏洞獲取系統(tǒng)敏感信息。最近比較閑也好久沒(méi)寫公眾號(hào)了近期可能會(huì)陸陸續(xù)續(xù)的更新漏洞或者漏洞分析?。web.icon=="302464c3f6207d57240649926cfc7bd4"
漏洞位置是在ThirdImSyncForKKWebService.java中,漏洞類型是webservice soap類型的。以下代碼分析均為個(gè)人對(duì)代碼的理解如有分析不對(duì)的還請(qǐng)多擔(dān)待。
前面很簡(jiǎn)單就是RequestMapping({"/getTodo"})
該注解用于將 HTTP 請(qǐng)求映射到方法上,當(dāng)訪問(wèn)/getTodo
路徑時(shí),會(huì)調(diào)用getTodo
方法。然后NotifyTodoAppResult result = new NotifyTodoAppResult();
創(chuàng)建一個(gè)NotifyTodoAppResult
對(duì)象result
,該對(duì)象會(huì)存儲(chǔ)操作的結(jié)果,并作為返回值。然后就if判斷是否為空值。
接下來(lái)是String whereBlock= "";
初始化一個(gè)空字符串whereBlock
,用于構(gòu)建查詢的條件部分。HQLInfo info = new HQLInfo();
創(chuàng)建一個(gè)HQLInfo
對(duì)象info
,該對(duì)象可能包含了 HQL 查詢所需的信息。List<HQLParameter> paramList = new ArrayList();
創(chuàng)建一個(gè)空的paramList
列表,用來(lái)存儲(chǔ)查詢條件的參數(shù)。
剩余的不重要直接跳到重點(diǎn),根據(jù)前面的代碼可以判斷出如果type
不是13
執(zhí)行以下代碼。whereBlock = whereBlock + this.getTodoSqlBlock("type", type, paramList);
調(diào)用getTodoSqlBlock
方法,傳入"type"
、type
和paramList
,向whereBlock
添加對(duì)應(yīng)的 SQL 查詢條件。
whereBlock = whereBlock + this.getTodoSqlBlock("type", type, paramList);
我們開始追蹤this.getTodoSqlBlock方法,代碼如下
getTodoSqlBlock方法中調(diào)用了keyword,value,hqlParam參數(shù),而hqlParam參數(shù)是用于存儲(chǔ)查詢條件參數(shù)的列表HQLParameter用于動(dòng)態(tài)構(gòu)建 HQL 查詢的參數(shù)。然后調(diào)用了第二個(gè)重載方法getTodoSqlBlock。
private String getTodoSqlBlock(String keyword, Object value, List
hqlParam) {
return this.getTodoSqlBlock(keyword, value, "=", keyword, hqlParam);
}
在這段代碼中我們需要重點(diǎn)關(guān)注是hqlParam.add(new HQLParameter(extendKey, value)); 向hqlParam列表中添加一個(gè)新的HQLParameter對(duì)象,extendKey作為參數(shù)的名字,value作為參數(shù)的值。我們追蹤HQLParameter。
private String getTodoSqlBlock(String keyword, Object value, String optStr, String extendKey, List
hqlParam) {
hqlParam.add(new HQLParameter(extendKey, value));
String key = keyword.substring(0, 1).toUpperCase() + keyword.substring(1);
return " and sysNotifyTodo.fd" + key + optStr + ":" + extendKey;
}
public HQLParameter(String name, Object value) {
this.name = name;
this.value = value;
}
這個(gè)構(gòu)造函數(shù)的作用是創(chuàng)建一個(gè)HQLParameter對(duì)象,并初始化它的 name和value屬性。HQLParameter類通常用于表示HQL(Hibernate Query Language)查詢中的參數(shù),在查詢構(gòu)建時(shí)使用,在這里可能包含查詢的字段名name和該字段的值value。這個(gè)類動(dòng)態(tài)構(gòu)建查詢條件時(shí)能夠方便地傳遞參數(shù)。
到這里可能大家會(huì)覺(jué)得這個(gè)webservice接口不就是HQL查詢嘛,別急我們接著往下走。根據(jù)剛才的分析type是由POST請(qǐng)求中嵌入了文件路徑的參數(shù)引發(fā)的而后從代碼邏輯來(lái)看type參數(shù)被傳遞給方法this.getTodoSqlBlock構(gòu)造了HQL查詢的一部分。這些最終的觸發(fā)點(diǎn)是調(diào)用了page=this.sysNotifyTodoService.findPage(info);來(lái)觸發(fā)查詢。最終是HQL查詢與ORM框架的處理,代碼中使用了HQL(Hibernate Query Language)查詢,whereBlock中包含了攻擊者傳入的參數(shù)type。ORM 框架(如 Hibernate 或 JPA)處理參數(shù)時(shí)可能會(huì)嘗試對(duì) file:// URI 進(jìn)行解析。這種行為通常發(fā)生在以下場(chǎng)景:
類型轉(zhuǎn)換:
框架可能會(huì)將 file:// 參數(shù)作為 URI 類型或資源類型進(jìn)行解析。
如果 fdType 是與文件、資源或流相關(guān)的字段(如 Blob、Clob 等),框架可能會(huì)嘗試加載對(duì)應(yīng)資源。
擴(kuò)展功能:
某些 ORM 框架支持使用 URI 直接指向文件或資源(通常用于存儲(chǔ)外部文件路徑)。
這類功能會(huì)隱式調(diào)用 Java 的 URL.openStream() 或 Files.newInputStream(),從而加載遠(yuǎn)程資源或本地文件。
由于本身webservice走的是soap協(xié)議,這里使用到了xop:IncludeSOAP 的 XOP 擴(kuò)展:
xop:Include 是 SOAP 附件優(yōu)化機(jī)制(XML-binary Optimized Packaging)。
如果服務(wù)器端 SOAP 框架支持 XOP,并未禁用 file:// 協(xié)議,它可能會(huì)嘗試解析 href 指向的文件內(nèi)容。
觸發(fā)條件:
如果服務(wù)器端解析 SOAP 的 type 字段時(shí),遇到 xop:Include 的 href 屬性,會(huì)調(diào)用底層的 URI 解析方法(如 new URL().openStream()),加載指定文件。
小結(jié)我們來(lái)捋一捋漏洞觸發(fā)的全過(guò)程
第一步:入口點(diǎn)是getTodo,用戶通過(guò)請(qǐng)求體傳入type參數(shù)。該參數(shù)通過(guò)this.getTodoSqlBlock方法構(gòu)造HQL查詢條件,最終被拼接到whereBlock中。
第二步:構(gòu)造HQL查詢條件getTodoSqlBlock方法被調(diào)用,用戶傳入的type添加到hqlParam中。
第三步:HQL查詢被執(zhí)行 page=this.sysNotifyTodoService.findPage(info);
第四步:文件解析觸發(fā),解析過(guò)程使用SOAP框架的xop:Include協(xié)議ORM 框架。
那么也就是說(shuō)最終觸發(fā)漏洞的是soap中包含了xop:Include標(biāo)簽,也就是我可以在poc中的任意位置插入paylaod,但是能夠被解析的前提是代碼中必須存在查詢或處理邏輯,能夠解析并利用傳入的參數(shù)內(nèi)容。
0x05 漏洞復(fù)現(xiàn)
根據(jù)以上代碼分析的結(jié)果構(gòu)造poc如下,參數(shù)是type,回顯是base64的然后解碼就行
剛才根據(jù)代碼分析也得知不是只有type這一處能夠解析,我們嘗試別的參數(shù)也可以正常文件讀取。
閱讀原文:https://mp.weixin.qq.com/s/t2KQOe3aGex5CPwa6kNFPg
該文章在 2024/12/19 17:43:36 編輯過(guò)