搜索
当前位置: sk彩票 > 对象图 >

级代码审计(第五课)NET Remoting反序列化漏洞

gecimao 发表于 2019-04-19 11:53 | 查看: | 回复:

  原标题:.NET高级代码审计(第五课).NET Remoting反序列化漏洞

  最近几天国外安全研究员Soroush Dalili(@irsdl)公布了.NET Remoting应用程序可能存在反序列化安全风险,当服务端使用HTTP信道中的SoapServerFormatterSinkProvider类作为信道接收器并且将自动反序列化TypeFilterLevel属性设置为Full的时候,会造成反序列化漏洞,从而实现远程RCE攻击。本文笔者从原理和代码审计的视角做了相关介绍和复现,并且归纳成.NET反序列化漏洞系列课程中的第五课。

  .NET Remoting是一种分布式应用解决方案,它允许不同AppDomain(应用程序域)之间进行通信,这里的通信可以是在同一个进程中进行或者一个系统中的不同进程间进行的通信。.NET Remoting框架也提供了多种服务,包括激活和生存期支持,以及负责与远程应用程序进行消息传输的通道。应用程序可在重视性能的场景下使用二进制数据传输,在需要与其他远程处理框架进行交互的场景下使用 XML 数据传输。在从一个AppDomain向另一个AppDomain传输消息时,所有的XML数据都使用 SOAP 协议,总体看.NET Remoting有以下三点优势:

  IpcChannel提供了使用Windows进程间通信(IPC)系统在同一计算机上的应用程序域之间传输消息的机制。在同一计算机上的应用程序域之间进行通信时,IPC信道比TCP或HTTP信道要快得多。但是IPC只在本机应用之间通信。所以,在客户端和服务端在同一台机器时,我们可以通过注册IpcChannel来提高Remoting的性能。但如果客户端和服务端不在同一台机器时,我们不能注册IPCChannel,在此不多介绍。

  TcpChannel提供了基于Socket 的传输工具,使用Tcp协议来跨越Remoting边界传输序列化的消息流。默认使用二进制格式序列化消息对象,具有更高的传输性能,适用于局域网。

  HttpChannel提供了一种使用Http协议,使其能在Internet上穿透防火墙传输序列化消息流,HttpChannel类型使用Soap格式序列化消息对象,因此它具有更好的互操作性。适用于广域网,如图

  研究漏洞之前先普及下HttpChannel的相关基础知识,HttpChannel类使用 SOAP 协议在远程对象之间传输消息,并且符合SOAP1.1的标准,所有的消息都是通过SoapFormatter传递,此格式化器会将消息转换为 XML数据并进行序列化,同时向数据流中添加所需的SOAP标头。如果指定了二进制格式化程序,则会创建二进制数据流。随后,将使用 HTTP 协议将数据流传输至目标URI。HttpChannel分类如图

  每行代码分别实现了创建服务端通道并且绑定本地端口9090;注册服务端通道;以及通过访问URI为RemoteObject.rem的地址调用远程的对象,在Remoting中有个激活方式的概念,表示在访问远程类型的一个对象实例之前,必须通过一个名为Activation的进程创建它并进行初始化。代码中引入了服务端激活的WellKnown方式,看下图

  WellKnown理解为知名对象的激活,服务器应用程序在激活对象实例之前会在统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象,它的激活分为SingleTon模式 、SingleCall模式,SingleTon类所代表的类型规定每个AppDomain只能存在一个实例,当SingleTon类型加载到AppDomain的时候,CLR调用它的静态构造器去构造一个SingleTon对象,并将它的引用保存到静态字段中,而且该类也没有提供任何的公共构造器方法,这就防止了其他任何代码构造该类的其他实例。具体到这两种模式各有区别,都可以触发漏洞,因不是重点所以不做过多介绍。

  RemoteObject继承自MarshalByRefObject类,MarshalByRefObject类(按引用封送)支持远程处理的应用程序中跨应用程序域(AppDomain)边界访问对象,同一应用程序域中的对象直接通信。不同应用程序域中的对象的通信方式有两种:跨应用程序域边界传输对象副本、通过代理交换消息,MarshalByRefObject类本质上通过引用代理交换消息来跨应用程序域边界进行通信的对象的基类。

  在序列化的时候调用格式化器的Serialize方法,传递对流对象的引用和想要序列化的对象图引用的两个参数,流对象可以是从System.IO.Stream类派生出来的任意对象,比如常见的MemoryStream、FileStream等,简单的说就是通过格式化器的Serialize方法可将对象图中所有对象都被序列化到流里去,通过Deserialize方法将流反序列化为对象图。

  当取值为Low的时候,代表Framework 远程处理较低的反序列化级别,只支持基本远程处理功能相关联的类型,而取值为Full的时候则支持所有类型在任意场景下远程处理都支持,所以取值为Full的时候,存在着严重的安全风险。

  VulnerableDotNetHTTPRemoting项目中用到就是第三种攻击方法,由于Remoting客户端在攻击中用途不大,故笔者不做赘述。

  GetObjectData方法的功能是调用SerializationInfo类型提供的SetType方法设置类型转换器,使用提供的AddValue多个重载方法来指定要序列化的信息,针对要添加的添加的每个数据,都要调用一次AddValue,GetObjectData添加好所有必要的序列化信息后会返回到类型解析器,类型解析器获取已经添加到SerializationInfo对象的所有值,并把他们都序列化到流中,代码逻辑实现部分参考如下

  又因为SoapServerFormatterSinkProvider类用SoapFormatter格式化器处理数据,所以客户端提交的数据肯定是SOAP消息,SOAP是基于XML的简易协议,让应用程序在HTTP上进行信息交换用的。为了给出标准的SOAP有效负载,笔者参考微软官方给的Demo

  由于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,这样的请求方式或许能更好的躲避和穿透防护设备。

本文链接:http://moodyjews.net/duixiangtu/107.html
随机为您推荐歌词

联系我们 | 关于我们 | 网友投稿 | 版权声明 | 广告服务 | 站点统计 | 网站地图

版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright @ 2012-2013 织梦猫 版权所有  Powered by Dedecms 5.7
渝ICP备10013703号  

回顶部