.NET高級代碼審計(第五課) .NET Remoting反序列化漏洞

来源:https://www.cnblogs.com/Ivan1ee/archive/2019/04/11/10691931.html
-Advertisement-
Play Games

0x00 前言 最近幾天國外安全研究員Soroush Dalili (@irsdl)公佈了.NET Remoting應用程式可能存在反序列化安全風險,當服務端使用HTTP通道中的SoapServerFormatterSinkProvider類作為通道接收器並且將自動反序列化TypeFilterLev ...


0x00 前言

最近幾天國外安全研究員Soroush Dalili (@irsdl)公佈了.NET Remoting應用程式可能存在反序列化安全風險,當服務端使用HTTP通道中的SoapServerFormatterSinkProvider類作為通道接收器並且將自動反序列化TypeFilterLevel屬性設置為Full的時候會造成反序列化漏洞,從而實現遠程RCE攻擊,本文筆者從原理和代碼審計的視角做了相關介紹和復現,並且歸納成.NET反序列化漏洞系列課程中的第五課

0x01 .NET Remoting概念

 .NET Remoting是一種分散式應用解決方案,它允許不同AppDomain(應用程式域)之間進行通信,這裡的通信可以是在同一個進程中進行或者一個系統中的不同進程間進行的通信。.NET Remoting框架也提供了多種服務,包括激活和生存期支持,以及負責與遠程應用程式進行消息傳輸的通道。應用程式可在重視性能的場景下使用二進位數據傳輸,在需要與其他遠程處理框架進行交互的場景下使用 XML 數據傳輸。在從一個AppDomain向另一個AppDomain傳輸消息時,所有的XML數據都使用 SOAP 協議,總體看.NET Remoting有以下三點優勢:

0x02 .NET Remoting通道和協議

 通道是Server和Client進行通信用的,在.NET Remoting中提供了三種通道類型,

IpcChannel提供了使用Windows進程間通信(IPC)系統在同一電腦上的應用程式域之間傳輸消息的機制。在同一電腦上的應用程式域之間進行通信時,IPC通道比TCP或HTTP通道要快得多。但是IPC只在本機應用之間通信。所以,在客戶端和服務端在同一臺機器時,我們可以通過註冊IpcChannel來提高Remoting的性能。但如果客戶端和服務端不在同一臺機器時,我們不能註冊IPCChannel,在此不多介紹。

TcpChannel提供了基於Socket 的傳輸工具,使用Tcp協議來跨越Remoting邊界傳輸序列化的消息流。預設使用二進位格式序列化消息對象,具有更高的傳輸性能,適用於區域網。

HttpChannel提供了一種使用Http協議,使其能在Internet上穿透防火牆傳輸序列化消息流,HttpChannel類型使用Soap格式序列化消息對象,因此它具有更好的互操作性。適用於廣域網,如圖

0x03 攻擊原理

研究漏洞之前先普及下HttpChannel的相關基礎知識,HttpChannel類使用 SOAP 協議在遠程對象之間傳輸消息,並且符合SOAP1.1的標準,所有的消息都是通過SoapFormatter傳遞,此格式化器會將消息轉換為 XML數據併進行序列化,同時向數據流中添加所需的SOAP標頭。如果指定了二進位格式化程式,則會創建二進位數據流。隨後,將使用 HTTP 協議將數據流傳輸至目標URI。HttpChannel分類如圖

下麵是從微軟文檔里摘取定義服務端的代碼片段:

每行代碼分別實現了創建服務端通道並且綁定本地埠9090;註冊服務端通道;以及通過訪問URI為RemoteObject.rem的地址調用遠程的對象,在.NET Remoting中有個激活方式的概念,表示在訪問遠程類型的一個對象實例之前,必須通過一個名為Activation的進程創建它併進行初始化。代碼中引入了服務端激活的WellKnown方式,看下圖

WellKnown理解為知名對象的激活,伺服器應用程式在激活對象實例之前會在統一資源標識符(URI)上來發佈這個類型。然後該伺服器進程會為此類型配置一個WellKnown對象,並根據指定的埠或地址來發佈對象,它的激活分為SingleTon模式 、SingleCall模式,SingleTon類所代表的類型規定每個AppDomain只能存在一個實例,當SingleTon類型載入到AppDomain的時候,CLR調用它的靜態構造器去構造一個SingleTon對象,並將它的引用保存到靜態欄位中,而且該類也沒有提供任何的公共構造器方法,這就防止了其他任何代碼構造該類的其他實例。具體到這兩種模式各有區別,都可以觸發漏洞,因不是重點所以不做過多介紹。

3.1、遠程對象

圖中的RemoteObject類,這是一個遠程對象,看下微軟官方的定義

RemoteObject繼承自MarshalByRefObject類,MarshalByRefObject類(按引用封送)支持遠程處理的應用程式中跨應用程式域(AppDomain)邊界訪問對象,同一應用程式域中的對象直接通信。不同應用程式域中的對象的通信方式有兩種:跨應用程式域邊界傳輸對象副本、通過代理交換消息,MarshalByRefObject類本質上通過引用代理交換消息來跨應用程式域邊界進行通信的對象的基類。

3.2、服務端

創建服務端的通道分為HttpServerChannel、HttpChannel,其中HttpServerChannel類有多個重載方法,需要知道和漏洞相關的兩個重載是發生在參數IServerChannelSinkProvider,它表示服務端遠程消息流的通道接收器

 

IServerChannelSinkProvider派生出多個類,例如BinaryServerFormatterSinkProvider、SoapServerFormatterSinkProvider類,如下圖

SoapServerFormatterSinkProvider類實現了這個介面,並使用SoapFormatter格式化器序列化對象,如下圖

SoapFormatter格式化器實現了System.Runtime.Serialization.IFormatter介面,IFormatter介面包括了Serialize、Deserialize方法,提供了序列化對象圖的功能。

在序列化的時候調用格式化器的Serialize方法,傳遞對流對象的引用和想要序列化的對象圖引用的兩個參數,流對象可以是從System.IO.Stream類派生出來的任意對象,比如常見的MemoryStream、FileStream等,簡單的說就是通過格式化器的Serialize方法可將對象圖中所有對象都被序列化到流里去,通過Deserialize方法將流反序列化為對象圖。

介紹完SoapFormatter之後回過頭來繼續看SoapServerFormatterSinkProvider類,它有一個重要的屬性TypeFilterLevel,表示當前自動反序列化級別,支持的值為Low(預設)和FULL。

當取值為Low的時候,代表.NET Framework 遠程處理較低的反序列化級別,只支持基本遠程處理功能相關聯的類型,而取值為Full的時候則支持所有類型在任意場景下遠程處理都支持,所以取值為Full的時候,存在著嚴重的安全風險

梳理一下HTTP通道攻擊的前置條件,第一步實例化SoapServerFormatterSinkProvider類並且設置TypeFilterLevel屬性為Full;第二步實例化HttpServerChannel/HttpChannel類,

使用下列三種重載方法實現傳入參數SoapServerFormatterSinkProvider

  • 滿足攻擊者需求的第1個攻擊重載方法是public HttpServerChannel(IDictionary properties, IServerChannelSinkProvider sinkProvider);

這裡筆者用VulnerableDotNetHTTPRemoting項目中的VulnerableDotNetHTTPRemotingServer類來改寫官方Demo 。IDictionary集合存放當前通道的配置信息,如圖

  • 滿足攻擊者需求的第2個攻擊重載方法是public HttpServerChannel(string name, int port, IServerChannelSinkProvider sinkProvider);

  • 滿足攻擊者需求的第3個攻擊方法是位於HttpChannel類下的 public HttpChannel(IDictionary properties, IClientChannelSinkProvider clientSinkProvider, IServerChannelSinkProvider serverSinkProvider)

VulnerableDotNetHTTPRemoting項目中用到就是第三種攻擊方法,由於.NET Remoting客戶端在攻擊中用途不大,故筆者不做贅述。

0x04 打造Poc

國外研究者發現Microsoft.VisualStudio.Text.UI.Wpf.dll 中的Microsoft.VisualStudio.Text.Formatting.TextFormattingRunProperties類實現了ISerializable介面,這個介面可以對序列化/反序列化的數據進行完全的控制,並且還避免了反射機制, 但有個問題Microsoft.VisualStudio.Text.UI.Wpf.dll需要安裝VisualStudio ,在非開發主機上不會安裝,但研究者後來發現Microsoft.VisualStudio.Text.Formatting.TextFormattingRunProperties類在Windows預設安裝的Microsoft.PowerShell.Editor.dll里也同樣存在,反編譯得到源碼,

 

實現了ISerializable介面,ISerializable只有一個方法,即 GetObjectData,如果一個對象的類型實現了ISerializable介面,會構造出新的System.Runtime.Serialization.SerializationInfo對象,這個對象包含了要為對象序列化的值的集合。

GetObjectData方法的功能是調用SerializationInfo類型提供的SetType方法設置類型轉換器,使用提供的AddValue多個重載方法來指定要序列化的信息,針對要添加的每個數據,都要調用一次AddValue,GetObjectData添加好所有必要的序列化信息後會返回到類型解析器,類型解析器獲取已經添加到SerializationInfo對象的所有值,並把他們都序列化到流中,代碼邏輯實現部分參考如下

TextFormattingRunProperties類中的ForegroundBrush屬性支持XAML數據,攻擊者可以引入《.NET高級代碼審計(第一課) XmlSerializer反序列化漏洞》同樣的攻擊載荷,如下

又因為SoapServerFormatterSinkProvider類用SoapFormatter格式化器處理數據,所以客戶端提交的數據肯定是SOAP消息,SOAP是基於XML的簡易協議,讓應用程式在HTTP上進行信息交換用的。為了給出標準的SOAP有效負載,筆者參考微軟官方給的Demo

結合Soroush Dalili (@irsdl)給出的有效載荷,元素a1指向的命名空間正是TextFormattingRunProperties類所在空間地址

在<a1:TextFormattingRunProperties></a1:TextFormattingRunProperties>元素內添加了屬性ForegroundBrush,在ForegroundBrush元素內帶入ResourceDictionary,這樣SOAP消息的攻擊載荷主體就完成了。@irsdl給出的有效載荷如下

由於.NET Remoting只支持SOAP 1.1,所以要指定SOAPAction,說來也奇怪這個SOAPAction的值是個URI,但是這個URI不必對應實際的位置。SOAPAction Header選項在SOAP1.2版本已經移除。另外一點圖上請求URI中的擴展名是rem,如果生產環境部署在IIS里,預設調用.NET應用模塊IsapiModule來處理HttpRemoting,所以在白盒審計或者黑盒滲透的時候遇到rem擴展名,就得考慮可能開啟了.NET Remoting應用。

還有一處需要註意,HTTP請求有個擴展方法M-POST,其中的其中的M表示Mandatory(必須遵循的,強制的),如果一個HTTP請求包含至少一個強制的擴充聲明,那麼這個請求就稱為強制的請求。強制請求的請求方法名字必須帶有“M-”首碼,例如,強制的POST方法稱為M-POST,這樣的請求方式或許能更好的躲避和穿透防護設備。

 

0x05 代碼審計

5.1SoapServerFormatterSinkProvider

從SoapServerFormatterSinkProvider類分析來看,需要滿足屬性TypeFilterLevel的值等於TypeFilterLevel.Full,可觸發的通道包括了HttpChannel類、HttpServerChannel類,這個攻擊點的好處在於發送HTTP SOAP消息,可很好的穿透防火牆。

5.2BinaryServerFormatterSinkProvider

從BinaryServerFormatterSinkProvider類分析來看,也需要滿足屬性TypeFilterLevel的值等於TypeFilterLevel.Full,可觸發的通道包括了TcpChannel類、TcpServerChannel類,這個攻擊點可反序列化二進位文件,筆者由於時間倉促,暫時不做分析跟進,有興趣的朋友可自行研究。

0x06 復盤

筆者將VulnerableDotNetHTTPRemoting項目部署到虛擬機,運行Server端,打開了本地埠1234

Burpsuite請求後成功彈出計算器,感謝Soroush Dalili (@irsdl)的分享。

0x07 總結

.NET Remoting技術已經出來很多年了,現在微軟主推WCF來替代它,在開發中使用概率越來越低,從漏洞本身看只要沒有設置SoapServerFormatterSinkProvider類屬性TypeFilterLevel=Full就不會產生反序列化攻擊(預設就是安全的)最後.NET反序列化系列課程筆者會同步到 https://github.com/Ivan1ee/https://ivan1ee.gitbook.io/ ,後續筆者將陸續推出高質量的.NET反序列化漏洞文章,歡迎大伙持續關註,交流,更多的.NET安全和技巧可關註實驗室公眾號。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一. 概述 本篇開始進入IS4實戰學習,從第一個示例開始,該示例是 “使用客戶端憑據保護API”,這是使用IdentityServer保護api的最基本場景。該示例涉及到三個項目包括:IdentityServer項目、API項目、Client項目,都有自己的宿主,為了方便開發,放在了一個解決方案下( ...
  • 導入導出的方法以及引用,可以自行創建一個幫助類 using System;using NPOI.SS.UserModel;using NPOI.XSSF.UserModel;using NPOI.HSSF.UserModel;using System.IO;using System.Data;usi ...
  • 背景 1. 基於之前 "基於Log4Net本地日誌服務簡單實現" 實現本地日誌服務,但是隨著項目開發演進,本地日誌服務滿足不了需求,譬如在預發佈環境或者生產環境,不可能讓開發人員登錄查看本地日誌文件分析。 2. Kafka+ELK日誌服務套件,可以線上日誌服務可以解決上述問題,並且提供豐富報表分析等 ...
  • 1. 下載windbg並安裝。 我下載的是 Windbg 6.12。註意,windbg分32位和64位,由分析環境的位數決定。我這裡安裝的是32位的。安裝過程很簡單,一路next就可以。 2. 準備被調試的程式。 新建一個C#控制台程式,使用如下代碼。編譯~ class Program { stat ...
  • 我們在用EF從資料庫生成模型的時候,預設實體類是沒有註釋的,但是我們已經在資料庫欄位添加說明瞭,能不能自動把註釋也拿過來? 答案是:能。 那麼我們開始 首先隨便開一個ASP.NET MVC項目,我們添加ADO實體數據模型。添加完成後我們打開userinfo.cs(這裡我的模型名稱為userinfo) ...
  • 委托:顧名思義,讓別人幫你辦件事。委托是C#實現回調函數的一種機制。可能有人會問了,回調函數是個啥??? 舉個例子:我現在是一家公司的老闆,公司現在在招聘.NET工程師,我們有一個小姐姐專門負責接受求職者投遞的簡歷,我就告訴這個小姐姐,一旦收到新的簡歷就轉發給我一份。 這個例子里小姐姐要做的工作:給 ...
  • Asp .Net Core 如何讀取appsettings.json配置文件?最近也有學習到如何讀取配置文件的,主要是通過 IConfiguration,以及在Program中初始化完成的。那麼今天給大家介紹下具體如何讀取配置文件的。 首先創建一個讀取配置文件的公共類GetAppsetting,我們 ...
  • 索引: 目錄索引 一.API 列表 1.UpdateAsync() 用於 單表 更新操作 二.API 單表-便捷 方法 舉例-01 生成 SQL 如下: 三.API 單表-便捷 方法 舉例-02 生成 SQL 如下 蒙 2019-04-11 19:45 周四 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...