设为首页 加入收藏

TOP

.NET高级代码审计(第五课) .NET Remoting反序列化漏洞(一)
2019-09-17 19:07:14 】 浏览:69
Tags:.NET 高级 代码 审计 第五 Remoting 序列化 漏洞

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类

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇13.翻译系列:Code-First方式配置.. 下一篇EF生成实体自动添加数据库字段注..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目