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安全和技巧可关注实验室公众号。

.NET高级代码审计(第五课) .NET Remoting反序列化漏洞的更多相关文章

  1. .NET高级代码审计(第一课)XmlSerializer反序列化漏洞

    0X00 前言 在.NET 框架中的 XmlSerializer 类是一种很棒的工具,它是将高度结构化的 XML 数据映射为 .NET 对象.XmlSerializer类在程序中通过单个 API 调用 ...

  2. .NET高级代码审计(第二课) Json.Net反序列化漏洞

    0X00 前言 Newtonsoft.Json,这是一个开源的Json.Net库,官方地址:https://www.newtonsoft.com/json ,一个读写Json效率非常高的.Net库,在 ...

  3. .NET高级代码审计(第三课)Fastjson反序列化漏洞

    0X00 前言 Java中的Fastjson曾经爆出了多个反序列化漏洞和Bypass版本,而在.Net领域也有一个Fastjson的库,作者官宣这是一个读写Json效率最高的的.Net 组件,使用内置 ...

  4. .NET高级代码审计(第四课) JavaScriptSerializer反序列化漏洞

    0X00 前言 在.NET处理 Ajax应用的时候,通常序列化功能由JavaScriptSerializer类提供,它是.NET2.0之后内部实现的序列化功能的类,位于命名空间System.Web.S ...

  5. [代码审计]四个实例递进php反序列化漏洞理解【转载】

    原作者:大方子 原文链接:https://blog.csdn.net/nzjdsds/article/details/82703639 0x01 索引 最近在总结php序列化相关的知识,看了好多前辈师 ...

  6. 【C语言探索之旅】 第二部分第五课:预处理

    内容简介 1.课程大纲 2.第二部分第五课: 预处理 3.第二部分第六课预告:   创建你自己的变量类型 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语 ...

  7. 【C语言探索之旅】 第一部分第五课:运算那点事

    内容简介 1.课程大纲 2.第一部分第五课:运算那点事 3.第一部分第六课预告:条件表达式 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏 ...

  8. NeHe OpenGL教程 第四十五课:顶点缓存

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. kali linux 渗透测试视频教程 第五课 社会工程学工具集

    第五课 社会工程学工具集 文/玄魂 教程地址:http://edu.51cto.com/course/course_id-1887.html   目录 第五课社会工程学工具集 SET SET的社会工程 ...

随机推荐

  1. Max Chunks To Make Sorted II LT768

    This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...

  2. spring security 4.2后出现CouldnotverifytheprovidedCSRFtokenbecauseyoursessionwasnotfound

    升级到spring security 4.2后,登录不了,出现下面的错误 WARN DefaultHandlerExceptionResolver:361 - Failed to bind reque ...

  3. Go环境下,编译运行etcd与goreman集群管理(1)

    Go环境下编译运行etcd与goreman管理 近几年了Go在比特币.区块链.云服务等相关重要领域贡献突出,作为IT行业的传承“活到老.学到光头”,保持学习心态. 周末放假,补充一二 主题:在Go环境 ...

  4. @Html.EditorFor() 用法

    @Html.EditorFor()返回一个由表达式表示的对象中的每个属性所对应的input元素,主要是针对强类型,一般这种方式用得多些a.@Html.EditorFor(mode=>mode.N ...

  5. python的数字图像处理学习(3)

    高级滤波: from skimage import data,color,data_dir import matplotlib.pyplot as plt from skimage.morpholog ...

  6. 整合SPRING CLOUD云服务架构 - 企业分布式微服务云架构构建

    整合SPRING CLOUD云服务架构 - 企业分布式微服务云架构构建 1.   介绍 Commonservice-system是一个大型分布式.微服务.面向企业的JavaEE体系快速研发平台,基于模 ...

  7. mybatis分页插件Mybatis_PageHelper 简单案例

    源码地址(官网,文档) 使用条件: 支持mybatis 3.1.0+ sql 解析工具(jsqlparser.jar) 下载 Mybatis_PageHelper  版本随意,反正我用的5.0.0 m ...

  8. 将excel的数据导入到数据库后都乱码了是怎么回事

    将excel内容首先保存成csv格式,然后在MySQL数据库中导入,结果汉字出现了乱码. 解决过程: 1.csv文件以txt形式打开,另存为,选择utf-8编码. 2.数据库,设置,collation ...

  9. Linux 第三天

    2.文件处理命令 1)touch 创建空文件 语法:touch文件名 2)cat 显示文件内容 英文原意:concatenate 语法:cat 文件名 常用选项: -n:number,显示行号 3)t ...

  10. java常用设计模式十一:策略模式

    一.概述 定义:策略模式是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化.(概念不好理解,可以看第二节的合例子) 基本角色: 环境( ...