长亭百川云 - 文章详情

CVE-2022-28684 .NET 最强大 UI 框架 DevExpress 如何绕过反序列化绑定类型限制实现 RCE

自在安全

71

2024-07-13

★且听安全-点关注,不迷路!

★漏洞空间站-优质漏洞资源和小伙伴聚集地!

**漏洞信息
**

使用 C# 做过界面开发的小伙伴应该对 DevExpress 框架库非常熟悉,它是一套基于 .Net 的 UI 控件库,也是目前 .Net 下最为强大的完整的一套 UI 控件库,主要集成了 WinForm 和 WebForm 下的一些常用控件和 UI 元素。

在分析绕过 `SerializationBinder` 不安全的类型绑定过程中,关注到了 DevExpress CVE-2022-28684 反序列化漏洞。ZDI 通报如下:

影响版本如下:

  • DevExpress: before 18.1.18, 18.2.17, 19.1.15, 19.2.14, 20.1.15, 20.2.11, 21.1.9, 21.2.7, 22.1.1

在阅读文章开始前,建议小伙伴们先移步公众号的前一篇文章:

.NET反序列化漏洞之绕过 SerializationBinder 不安全的类型绑定

QCyber,公众号:且听安全.NET反序列化漏洞之绕过 SerializationBinder 不安全的类型绑定

大家更加关注有实际影响力的漏洞,但是我觉得对想学习漏洞挖掘和代码审计的小伙伴而言,分析基础框架的通用性漏洞更有价值。

**SafeBinaryFormatter
**

在 DevExpress 提供了一个 `SafeBinaryFormatter` 的安全反序列化静态类:

对外提供了三个反序列化函数接口:

我们可以尝试调用 `Deserialize` 来加载 `YSoSerial.Net` 生成的反序列化载荷:

`using (var fileStream = new FileStream(file, FileMode.Open))``{`    `SafeBinaryFormatter.Deserialize(fileStream);``}`

抛出异常,无法像直接使用 .NET 官方提供的 `BinaryFormatter` 那样实现 RCE :

失败原因分析

`SafeBinaryFormatter#Deserialize` 反序列化处理过程:

跟进 `DeserializeWithSecurityExceptionUnwrap` 函数:

通过 `Instance` 只读属性获取 `BinaryFormatter` 对象,然后调用 `BinaryFormatter#Deserialize` 执行反序列化操作。我们重点看一下 `BinaryFormatter` 的定义过程:

到这里大家就明白了失败的原因。`SafeBinaryFormatter` 自定义的 `BinaryFormatter` 对象在初始化时会绑定一个继承于 `SerializationBinder` 的 `DXSerializationBinder` 对象,限制反序列化操作的代码位于 `DXSerializationBinder#BindToType` 函数中:

跟进分析 `DXSerializationBinder#BindToType` 函数:

进入 `SafeSerializationBinder#Ensure` :

首先利用 `UnsafeType#Match` 进行匹配,匹配成功将调用 `XtraSerializationSecurityTrace.UnsafeType` 断言判断抛出异常。`UnsafeType#Match` 定义如下:

`public static bool Match(string assembly, string type)``{`  `return SafeSerializationBinder.TypeRanges.Match(SafeSerializationBinder.UnsafeTypes.typeRanges, assembly, type) ||`  `SafeSerializationBinder.TypeRanges.MatchDX(SafeSerializationBinder.UnsafeTypes.dxTypeRanges, assembly, type) ||`  `SafeSerializationBinder.UnsafeTypes.types.Contains(type) ||`  `(FrameworkVersions.IsMonoRuntime &&SafeSerializationBinder.UnsafeTypes.wasmTypes.Contains(type));``}`

`SafeSerializationBinder.UnsafeTypes.typeRanges` 定义如下:

`SafeSerializationBinder.UnsafeTypes.dxTypeRanges` 定义如下:

`SafeSerializationBinder.UnsafeTypes.types` 定义如下:

`private static readonly HashSet<string> types = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)``{`  `"System.DelegateSerializationHolder",`  `"System.DelegateSerializationHolder+DelegateEntry",`  `"System.Reflection.MemberInfoSerializationHolder",`  `"System.UnitySerializationHolder",`  `"System.Management.Automation.PSObject",`  `"System.Workflow.ComponentModel.Serialization.ActivitySurrogateSelector",`  `"System.AppDomainSetup",`  `"System.Exception",`  `"System.BadImageFormatException",`  `"System.MissingFieldException",`  `"System.MissingMemberException",`  `"System.MissingMethodException",`  `"System.IO.FileLoadException",`  `"System.IO.FileNotFoundException",`  `"System.Security.SecurityException",`  `"System.Security.Permissions.PublisherIdentityPermissionAttribute",`  `"System.Security.Permissions.PermissionSetAttribute",`  ``"System.Collections.Generic.ComparisonComparer`1",``  `"System.Reflection.RuntimeAssembly",`  `"System.Reflection.DefaultMemberAttribute",`  `"System.Reflection.Emit.ModuleBuilderData",`  `"System.Net.FileWebRequest",`  `"System.Net.HttpWebRequest",`  `"System.Media.SoundPlayer",`  `"System.Configuration.ConfigurationException",`  `"System.Runtime.Versioning.FrameworkName",`  `"System.Drawing.Design.ToolboxItem",`  `"System.RuntimeType",`  `"System.RuntimeTypeHandle",`  `"System.Resources.ResourceManager",`  `"System.Reflection.RuntimeConstructorInfo",`  `"System.Reflection.RuntimeEventInfo",`  `"System.Reflection.RuntimeFieldInfo",`  `"System.Reflection.RuntimeMethodInfo",`  `"System.Reflection.RuntimePropertyInfo",`  `"System.Reflection.RuntimeParameterInfo",`  `"System.Reflection.RuntimeModule",`  `"System.Reflection.RtFieldInfo",`  `"System.Reflection.MdFieldInfo",`  `"System.Reflection.ParameterInfo",`  `"System.Reflection.Pointer",`  `"System.Reflection.TypeDelegator",`  `"System.Reflection.CustomAttributeTypedArgument",`  `"System.Runtime.CompilerServices.RequiredAttributeAttribute",`  `"System.Runtime.CompilerServices.StateMachineAttribute",`  `"System.Security.Permissions.ResourcePermissionBase",`  `"System.ComponentModel.LicenseException",`  `"System.CodeDom.Compiler.TempFileCollection",`  `"System.Data.DataSet"``};`

包括我们测试使用的 `System.Data.DataSet` 利用链在内的几乎所有 `YSoSerial.Net` 中已知的 Gadget ,调用过程在 `BindToType` 函数中抛出异常,最终导致反序列化操作被阻断。

阻断绕过(一)

回顾前面公众号文章《.NET反序列化漏洞之绕过 SerializationBinder 不安全的类型绑定》,我们可以通过修改 `YSoSerial.Net` 代码段 `/Generators/DataSetGenerator.cs` 来通过 `SafeSerializationBinder#Ensure` 检查:

继续往下走,发现 `EnsureAssemblyQualifiedTypeName` 函数会修改 `assemblyName` 和 `typeName` 的值,从而再次调用 `Ensure` 函数时还是会检查失败抛出异常:

跟进 `EnsureAssemblyQualifiedTypeName` 函数:

我们的目标是想让 `EnsureAssemblyQualifiedTypeName` 函数返回 `false` ,这样将可以避开 `Ensure` 函数对 `typeName` 的二次检查。一共有三处确定返回 `false` 的地方,我们可以重点关注第 88 行处的处理过程:

  •  `num2` 变量的取值为 `typeName` 最后一个 `,` 的索引;

  •   代码中会根据尝试截取生成新的 `typeName` ,截取的位置刚好就是 `num2` ;

  •   如果 `typeName` 中包含 `version=` ,将提取 `typeName` 最后一个 `]` 的位置并赋值给 `num4` ,当 `num4 > num2` 时函数将返回 `false`。

因此可以修改 `DataSetGenerator.cs` 代码中的 `GetObjectData` ,直接在后面添加 `,]` 就可以满足上面的条件,同时为了符合 .NET `Type` 全名命名规则,最终修改如下:

重新生成反序列化载荷再次测试:

返回 `false` ,绕过了 `Ensure` 函数对 `typeName` 的二次检查。

**阻断绕过二
**

回到 `BindToType` 函数继续往下走:

第 466 行 `SafeSerializationBinder.DXSerializationBinder#GetAssembly` 尝试根据 `assemblyName` 获取 `assembly` ,跟进:

第 488 行 `Assembly.Load` 加载不存在的组件名会导致 `BindToType` 函数返回 `null`:

在《.NET反序列化漏洞之绕过 SerializationBinder 不安全的类型绑定》中已经分析,当 `BindToType` 返回 `null` 时,还会继续调用 `FastBindToType` 对象:

因为 `assemblyName` 不存在会抛出异常,获取 `Type` 类型为空,从而导致反序列化操作再次被阻断。这个地方绕过很容易,我们再次修改  `DataSetGenerator.cs` 代码,在 `GetObjectData` 中赋值一个合理的组件名,比如 `System`:

再次测试成功通过 `FastBindToType` 组件检查并返回合法 `Type` :

最终触发 RCE。

**修复方式
**

漏洞修复主要位于 `EnsureAssemblyQualifiedTypeName` 函数,新增 `AssemblyQualifiedTypeNameParser` 密封类:

对参数  `assemblyName` 和 `typeName` 的处理和检查逻辑更加复杂,利用前面的方法无法绕过检查。

由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用本人负责,且听安全及文章作者不为此承担任何责任。

★且听安全-点关注,不迷路!****

★漏洞空间站-优质漏洞资源和小伙伴聚集地!

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2