經得起原始碼資安弱點掃描的程式設計習慣培養(二)_8.Insecure Deserialization :不安全的反序列化漏洞ASP.NET處理方式
近期在專案偕同上被Checkmarx掃碼掃到高風險的程式片段
偵測到Deserialization of Untrusted Data (OWASP 2017第8點Insecure Deserialization)
因此要做程式碼安全品質的修正
情境:
Call web api 回傳回來(讀取外部的json測試檔案)的json 字串要反序列化轉為DataTable
for GridView Bind呈現
CheckMarx掃碼報告給的說明
============================================================
Deserialization of Untrusted Data
風險:
對不受信任的資料進行反序列化,可能允許攻擊者提供惡意的物件給反序列化程式碼使用。如果危險物件被不安全地反序列化,則可能透過反序列化的過程中,呼叫可能可用的類別(Class)或方法(method)來執行程式碼或操作系統命令。
此外,反序列化可能會繞過邏輯驗證。由於反序列化通常使用自己的方法,從序列化資料中構造新物件,因此它可以繞過建構函數或setter中強制執行的檢查,這將允許攻擊者反序列化未經驗證不正確或完全惡意的物件。這可能會導致例外狀況,進而影響程式邏輯。
發生原因:
序列化和反序列化物件,對於遠端Web Service流程是不可或缺的,其中物件通過Web
Service(例如透過網路)在程式碼實作之間傳遞。在反序列化期間,從Web Service上提供的序列化物件建構新物件;但是,如果被反序列化的物件不受信任,則可能包含意外或有潛在危險的物件。
如何避免:
盡可能不要在遠端Web Service之間傳遞序列化物件。相反地,請考慮在Web Service之間傳遞原始值( value primitives),並使用這些值填入新建構的物件。如果需要,使用白名單方法傳遞物件。
務必確保傳遞的物件是已知的、可信的和可預期的。除非物件已經過驗證且屬於受信任的已知類型,並且不包含不受信任的物件,否則不要從任何來源動態建構物件。
============================================================
攻擊者在欲被反解譯(de-serialize)回物件的byte stream內容
中輸入自訂的字串以達到攻擊目標
Remote code execution
Denial of Service(DoS)
Access-control-related attacks
聽處理過有經驗的同事分享後得知
原因在於直接對string 也就是Stream 直接ReadToEnd()的結果直接做反序列化
會被掃瞄到這類風險被要求改正
Before:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | string testJsonFilePath = HttpContext.Current.Server.MapPath("~/json/rcmdAssg.json"); using (StreamReader streamReader = new StreamReader(testJsonFilePath)) { jsonResponse = streamReader.ReadToEnd(); } IC_RcmdAssg_Model iC_RcmdAssg_Model = Newtonsoft.Json.JsonConvert.DeserializeObject<IC_RcmdAssg_Model>(jsonResponse); DataTable dtRcmd = new DataTable(); dtRcmd.Columns.Add("isChked", Type.GetType("System.Boolean")); dtRcmd.Columns.Add("oriAssgName", Type.GetType("System.String")); dtRcmd.Columns.Add("oriAssgCountry", Type.GetType("System.String")); dtRcmd.Columns.Add("rcmdName", Type.GetType("System.String")); dtRcmd.Columns.Add("rcmdCountry", Type.GetType("System.String")); DataRow newRow; foreach (Assignee_List assgRcmd in iC_RcmdAssg_Model.assignee_list) { newRow = dtRcmd.NewRow(); newRow["isChked"] = true; newRow["oriAssgName"] = assgRcmd.oriAssgName; newRow["oriAssgCountry"] = assgRcmd.oriAssgName; newRow["rcmdName"] = assgRcmd.oriAssgName; newRow["rcmdCountry"] = assgRcmd.oriAssgName; dtRcmd.Rows.Add(newRow); } gvRcmdAssgData.DataSource = dtRcmd; gvRcmdAssgData.DataBind(); |
After:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | string testJsonFilePath = HttpContext.Current.Server.MapPath("~/json/rcmdAssg.json"); using (StreamReader streamReader = new StreamReader(testJsonFilePath)) { //jsonResponse = streamReader.ReadToEnd(); JsonSerializer jsonSerializer = new JsonSerializer(); IC_RcmdAssg_Model iC_RcmdAssg_Model = (IC_RcmdAssg_Model)jsonSerializer.Deserialize(streamReader, typeof(IC_RcmdAssg_Model)); DataTable dtRcmd = new DataTable(); dtRcmd.Columns.Add("isChked", Type.GetType("System.Boolean")); dtRcmd.Columns.Add("oriAssgName", Type.GetType("System.String")); dtRcmd.Columns.Add("oriAssgCountry", Type.GetType("System.String")); dtRcmd.Columns.Add("rcmdName", Type.GetType("System.String")); dtRcmd.Columns.Add("rcmdCountry", Type.GetType("System.String")); DataRow newRow; foreach (Assignee_List assgRcmd in iC_RcmdAssg_Model.assignee_list) { newRow = dtRcmd.NewRow(); newRow["isChked"] = false; newRow["oriAssgName"] = assgRcmd.oriAssgName; newRow["oriAssgCountry"] = assgRcmd.oriAssgCountry; newRow["rcmdName"] = assgRcmd.rcmdName; newRow["rcmdCountry"] = assgRcmd.rcmdCountry; dtRcmd.Rows.Add(newRow); } gvRcmdAssgData.DataSource = dtRcmd; gvRcmdAssgData.DataBind(); } |
通常這種反序列化情境
1.盡量避免用generic types 像是object 或是 dynamic這種,應提早就限制住反序列的物件型態。
2.使用Json.NET時候 請勿使用「無」以外的 TypeNameHandling
Ref:
Attacking .NET deserialization - Alvaro Muñoz
https://www.youtube.com/watch?v=eDfGpu3iE4Q&ab_channel=Scrtinsomnihack
STOP Insecure Deserialization with C#
https://medium.com/@tiagodaraujo/stop-insecure-deserialization-with-c-6a488c95cf2f
TypeNameHandling Enumeration
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm
CA2326:請勿使用「無」以外的 TypeNameHandling 值
https://docs.microsoft.com/zh-tw/dotnet/fundamentals/code-analysis/quality-rules/ca2326
CA2329: Do not deserialize with JsonSerializer using an insecure configuration
https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2329
留言
張貼留言