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