Dubbo3序列化安全機制導致的一次生產故障

前言

記錄一次 Dubbo 線上故障排查和原因分析。

線上 Dubbo 消費者啟動有錯誤日志如下,但是不影響服務啟動。

java.lang.TypeNotPresentException: Type org.example.model.ThirdParam not present
...
Caused by: java.lang.ClassNotFoundException: org.example.model.ThirdParam
...

緊接著,消費者發起 RPC 調用,偶發性報錯如下:

Caused by: org.apache.dubbo.remoting.RemotingException: 
Failed to send message Request [id=-7672337589162309142, version=2.0.2, twoWay=true, event=false, broken=false, mPayload=0, data=null] to /192.168.98.92:20880, 
cause: org.apache.dubbo.common.serialize.SerializationException: 
java.lang.IllegalArgumentException: [Serialization Security] 
Serialized class org.example.api.InnerParam is not in allow list. 
Current mode is `STRICT`, will disallow to deserialize it by default. 
Please add it into security/serialize.allowlist or follow FAQ to configure it.

消費者嘗試重啟,RPC 調用偶爾成功,偶爾失敗,沒有規律。

故障重現

為了重現故障,我寫了個示例工程,有四個模塊:

  • third-sdk

模擬依賴的三方 SDK,有兩個版本:V1.0 V2.0,區別是 ThirdParam 類只在 V2.0 才提供。

  • dubbo-api

Dubbo API 模塊,包含服務接口和參數類,依賴third-sdk V2.0

  • dubbo-provider

Dubbo 服務提供者,直接依賴dubbo-api,間接依賴third-sdk V2.0

  • dubbo-consumer

Dubbo 服務消費者,直接依賴dubbo-api,直接依賴third-sdk V1.0

重點:dubbo-consumer 模塊自身依賴了低版本的**<font style="color:#DF2A3F;">third-sdk</font>**,ThirdParam 類是不存在的。

dubbo-api模塊,IService 接口如下。InnerParam 類存在于當前模塊,ThirdParam 來自三方庫。

由于dubbo-consumer模塊依賴的是低版本的third-sdk,所以 ThirdParam 類不存在,但只要不調用 M2 就沒事。

public interface IService {String M1(InnerParam innerParam);String M2(Optional<ThirdParam> optional);
}

ServiceImpl.java和服務提供者的啟動和消費者的調用均不是重點,這里不貼代碼。

說明:為啥 M2 參數類型是Optional<ThirdParam>

因為如果參數類型直接是 ThirdParam,消費者啟動時,解析 Service Class 這一步就會因為 Class Not Found 直接報錯而退出進程。ThirdParam 必須是泛型,才不至于 Service Class 無法解析。

接著,啟動 Provider,啟動 Consumer,就能看到錯誤日志,但是不影響消費者啟動。

再接著,Consumer 發起 RPC 調用,就會報錯:

最快的修復方式,重構 IService.java ,方法名 M1 改為 a1

public interface IService {String a1(InnerParam innerParam);String M2(Optional<ThirdParam> optional);
}

接著,重啟 Provider,Consumer。Consumer 啟動依然有錯誤日志,但是不影響啟動。

Consumer 發起 a1 的 RPC 調用,成功,不再報錯。

call a1 start...
call a1 result: OK

為什么僅僅修改個方法名,RPC 調用就不再報錯了呢?

故障分析

已知,Dubbo 從 3.1.6 版本開始,為了避免序列化引起的 RCE 攻擊,引入了“序列化類檢查機制”。只有在信任白名單里的類,才允許被序列化和反序列化。

同時,為了避免開發者手動添加白名單帶來的額外負擔,Dubbo 默認開啟“自動信任機制”。即 Dubbo 會在 Service 暴露和引用的同時,自動信任 Service Class 依賴的相關類,這些類包括:Service Class 本身、父類和接口類型、屬性類型、方法的所有入參/出參類型、異常類型等,將它們全部加入到白名單里。

根據消費者報錯的信息來看,很明顯提示org.example.api.InnerParam類不在白名單里面,所以序列化失敗。

cause: org.apache.dubbo.common.serialize.SerializationException: 
java.lang.IllegalArgumentException: [Serialization Security] 
Serialized class org.example.api.InnerParam is not in allow list. 

由此我們推測,Dubbo 的“自動信任機制”出現了問題

通過源碼我們發現,Service 在暴露和引用的時候,默認會注冊 Service Class,方法是SerializeSecurityConfigurator#registerInterface

注冊接口就是將 Service Class 自身、以及超類、屬性類、方法的入參/出參、返回類型、異常類型等通通加入到白名單。

public synchronized void registerInterface(Class<?> clazz) {/*** 是否自動信任序列化類?默認是true* 默認會將 Service Class 涉及到的類加入白名單,全部信任*/if (!autoTrustSerializeClass) {return;}Set<Type> markedClass = new HashSet<>();/*** 1. 信任 Service Class 自身* 2. 根據 TrustSerializeClassLevel 信任所在包的層級* 3. 信任 Service Class 的接口、父類、屬性類型、*/checkClass(markedClass, clazz);addToAllow(clazz.getName());Method[] methodsToExport = clazz.getMethods();// 信任 Service Class 方法的入參、出參類型、拋出的異常類型for (Method method : methodsToExport) {Class<?>[] parameterTypes = method.getParameterTypes();for (Class<?> parameterType : parameterTypes) {checkClass(markedClass, parameterType);}Type[] genericParameterTypes = method.getGenericParameterTypes();for (Type genericParameterType : genericParameterTypes) {checkType(markedClass, genericParameterType);}Class<?> returnType = method.getReturnType();checkClass(markedClass, returnType);Type genericReturnType = method.getGenericReturnType();checkType(markedClass, genericReturnType);Class<?>[] exceptionTypes = method.getExceptionTypes();for (Class<?> exceptionType : exceptionTypes) {checkClass(markedClass, exceptionType);}Type[] genericExceptionTypes = method.getGenericExceptionTypes();for (Type genericExceptionType : genericExceptionTypes) {checkType(markedClass, genericExceptionType);}}
}

Dubbo 會遍歷 Service Class 所有方法,依次注冊方法的入參、出參到白名單。

問題就出在這個遍歷上,因為dubbo-consumer模塊直接依賴了third-sdk V1.0,對于方法IService#M2(Optional<ThirdParam>)的入參,ThirdParam 類是不存在的,導致整個注冊過程中斷跳出,后續方法的參數都沒有注冊到白名單,進而導致 Consumer 發起 RPC 調用時,參數序列化報錯。

另一個問題,為什么方法**IService#M1**重構為**IService#a1**,Consumer 就正常了呢?

這是因為方法簽名修改后,導致Class#getMethods返回的 Method 順序發生了改變,如果a1方法先于M2方法返回,讓中斷發生在a1方法注冊之后,雖然整個注冊過程還是會異常,但是org.example.api.InnerParam類已經添加到白名單了,對后續的 RPC 調用當然沒有影響。

注意:雖然示例中通過修改方法名來改變**Class#getMethods**返回的 Method 順序,但是強烈不建議這么做,因為 Java Doc 已經寫的非常清楚了,返回的方法數組沒有特定順序,取決于JVM實現。

The elements in the returned array are not sorted and are not in any particular order.

推薦的修復方式,Service Class 所有的方法入參和出參,都不應該直接用三方 SDK 的類,這本身就不規范。在 API 模塊新建 DTO 類,把三方類轉換成自己的 DTO 類。

尾巴

因為消費者模塊和公共 API 模塊依賴的三方庫版本不同,導致消費者模塊缺少一部分類,進而導致消費者在注冊 Service Class 方法參數到序列化白名單時,發生異常中斷跳出,沒有被信任的參數類,一旦序列化就會拋出異常。

又因為Class#getMethods返回的方法順序并不固定,就會導致方法參數偶爾被信任,偶爾不被信任,所以會出現服務重啟后可能又恢復正常的錯覺。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/96028.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/96028.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/96028.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

centos7 docker離線安裝

介紹 本文主要講了如何在完全沒網的情況下安裝docker&#xff08;適合于高網絡安全要求的企業&#xff09; 本文適用的centos版本&#xff1a; [root0001 temp]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) 采用docker in docker下載依賴 實際試驗后&…

東京本社招聘 | 財務負責人 多個日本IT崗位(Java/C++/Python/AWS 等),IT營業同步招募

大家好&#xff0c;本期為大家帶來我司在東京GSD本社及其他會社千葉地區的招聘崗位。 涵蓋 財務負責人、Java開發工程師、數據中心維護工程師、項目經理、IT營業 等多個職位。 歡迎有志之士加入&#xff01;&#x1f539; 財務負責人&#xff08;東京本社&#xff09;工作內容日…

四數之和

目錄 一&#xff1a;題目鏈接 二&#xff1a;題目思路 三&#xff1a;代碼實現 一&#xff1a;題目鏈接 理解題目需要注意&#xff0c;如果兩個四元組元素一一對應&#xff0c;則認為兩個四元組重復&#xff0c;選擇其中一個四元組即可。比如 [ 0 , 1 , 0 , 2] 和 [ 1 , …

【序列晉升】29 Spring Cloud Task 微服務架構下的輕量級任務調度框架

Spring Cloud Task作為微服務架構中的輕量級任務調度框架&#xff0c;為開發人員提供了一種構建短生命周期微服務任務的便捷方式。它允許開發者快速創建、執行和管理一次性任務或短期批處理作業&#xff0c;任務執行完成后自動關閉以釋放系統資源&#xff0c;避免了傳統長期運行…

【1分鐘速通】 HTML快速入門

HTML&#xff08;HyperText Markup Language&#xff0c;超文本標記語言&#xff09; 是構建網頁的基礎語言。它通過 標簽&#xff08;Tag&#xff09; 來描述網頁的結構和內容&#xff0c;常與 CSS&#xff08;負責樣式 – <style></style>&#xff09;和 JavaScr…

【GeoServer】WMS GetFeatureInfo URL 逐個參數解釋

我來把你構造的這個 WMS GetFeatureInfo URL 逐個參數解釋一下&#xff0c;方便你理解&#xff1a;http://127.0.0.1:8090/geoserver/xxxx/wms? SERVICEWMS& VERSION1.1.1& REQUESTGetFeatureInfo& QUERY_LAYERSloess:yourLayer& LAYERSloess:yourLayer& …

OBS直播教程:點歌直播間怎么弄?直播點歌用什么軟件?

OBS直播教程&#xff1a;點歌直播間怎么弄&#xff1f;直播點歌用什么軟件&#xff1f; 第一步&#xff1a;安裝OBS直播軟件&#xff0c;如果你電腦已經安裝了OBS&#xff0c;請直接看第二步 OBS直播軟件下載地址①&#xff1a; https://d.obscj.com/obs-Studio-29.1.3-Full-…

【數據庫】Redis詳解:內存數據庫與緩存之王

什么是Redis&#xff1f; Redis&#xff08;Remote Dictionary Server&#xff09;是一個開源的、基于內存的數據結構存儲系統&#xff0c;可以用作數據庫、緩存和消息代理。它支持多種數據結構&#xff0c;如字符串、哈希、列表、集合、有序集合等&#xff0c;具有極高的性能和…

【iOS】 單例模式

1. 認識單例模式首先讓我們先看下關于單例模式的定義&#xff08;來自于《設計模式》(Addison-Wesley,1994)&#xff09;一個類有且僅有一個實例&#xff0c;并且自行實例化向整個系統提供。如果說每一個人都是一個類&#xff0c;那么從他出生開始&#xff0c;他就是生活中的唯…

多目標輪廓匹配

前面我們使用模板匹配&#xff0c;得到的結果都是一個圖&#xff0c;那么如果我們圖片中有許多我們的目標&#xff0c;那么該如何找出來呢&#xff1f;如上我們圖片中有許多箭頭和我們的模板一致&#xff0c;只不過方向不對&#xff0c;那么該如何匹配呢&#xff1f;圖片和模板…

【C++】簡單介紹lambda表達式

各位大佬好&#xff0c;我是落羽&#xff01;一個堅持不斷學習進步的學生。 如果您覺得我的文章還不錯&#xff0c;歡迎多多互三分享交流&#xff0c;一起學習進步&#xff01; 也歡迎關注我的blog主頁: 落羽的落羽 文章目錄一、 什么是lambda表達式二、 表達式語法三、lambd…

磁共振成像原理(理論)4:自由進動和弛豫 (Free Precession and Relaxation)

當磁化自旋系統被射頻脈沖擾動而偏離其熱平衡態后&#xff0c;一旦移除外部激勵并給予足夠時間&#xff0c;系統將根據熱力學定律返回平衡態。這一過程包含三個特征現象&#xff1a; (a) 自由進動——宏觀磁化矢量 (M?\vec{M}M) 繞( B0?\vec {B_0}B0?? )場的進動&#xff1…

ubuntu 20.04 安裝spark

安裝openjdk21 下載 wget https://download.java.net/openjdk/jdk21/ri/openjdk-2135_linux-x64_bin.tar.gz解壓 tar -xvf openjdk-2135_linux-x64_bin.tar.gzsudo mv jdk-21/ /opt/jdk-21/設置環境變量 echo export JAVA_HOME/opt/jdk-21 | sudo tee /etc/profile.d/java2…

第三方區塊鏈應用測評:【多簽錢包合約安全評估_閾值簽名機制與私鑰存儲安全性測試】

閾值簽名機制安全測試密碼學審計 采用門限簽名方案&#xff08;TSS&#xff09;的多簽錢包需驗證其閾值BLS簽名或ECDSA簽名算法的正確性。測試重點包括&#xff1a;分布式密鑰生成&#xff08;DKG&#xff09;過程的保密性&#xff08;無密鑰信息泄露&#xff09;、簽名碎片驗證…

大模型處理長文檔的挑戰和解決方案?

當前&#xff0c;AI 應用正處于極速發展階段&#xff0c;大語言模型&#xff08;LLM&#xff09;與檢索增強生成&#xff08;RAG&#xff09;系統已成為構建智能問答、知識管理等高階 AI 應用的核心引擎&#xff0c;被廣泛應用于金融分析、學術研究、企業合規等多個領域。然而&…

JavaWeb--day1--HTMLCSS

(以下內容全部來自上述課程及課件) web開發介紹 1. 什么是web&#xff1f; Web&#xff1a;全球廣域網&#xff0c;也稱為萬維網&#xff0c;能夠通過瀏覽器訪問的網站。 2. Web網站的工作流程 3. Web標準 Web標準也稱為網頁標準&#xff0c;由一系列的標準組成&#xf…

OpenEuler安裝gitlab,部署gitlab-runner

目錄 一、安裝gitlab 二、安裝部署docker設置源 三、下載部署runner ?編輯 四、構建CI/CD 一、安裝gitlab 1.查看OpenEuler版本 [rootlocalhost ~]# cat /etc/os-release NAME"openEuler" VERSION"24.03 (LTS-SP1)" ID"openEuler" VERSI…

實戰項目-----在圖片 hua.png 中,用紅色畫出花的外部輪廓,用綠色畫出其簡化輪廓(ε=周長×0.005),并在同一窗口顯示

實戰項目實現以下功能&#xff1a;對圖片 hua.png 進行輪廓提取&#xff0c;并在同一窗口中完成以下兩個繪制操作&#xff1a;用紅色畫出花的外部輪廓&#xff08;即最外層輪廓&#xff09;用綠色畫出該輪廓的近似多邊形&#xff0c;其中近似精度參數 ε 設置為輪廓周長的 0.00…

開源鴻蒙北向框架開發:系統服務理論詳解

系統服務的啟動 基本可以認為&#xff1a;OpenHarmony 的系統服務進程都是“由 init 直接或間接拉起”的。 直接方式&#xff1a; init 按 /system/etc/init/.cfg 啟動可執行&#xff08;如 /system/bin/sa_main、/system/bin/samgr 等&#xff09;&#xff0c;這些進程的 PPid…

龍虎榜——20250909

上證指數今天縮量收陰線&#xff0c;跌破10日均線&#xff0c;目前日線總體處于高位寬幅震蕩中&#xff0c;小級別暫未明確方向&#xff0c;指數面臨方向選擇&#xff0c;需要注意高位股的風險。 深證指數今天縮量收陰線&#xff0c;跌破5日均線&#xff0c;接下來幾天方向的選…