9.DataContractJsonSerializer反序列化点

2024-10-24 18:53   广东  

1.DataContractJsonSerializer的基本使用

又是DataContract字辈的,在基本使用上和以前介绍过的几个DataContract序列化与反序列化是基本一致的,但这玩意是用于JSON格式数据的序列化与反序列化的。使用Y4er师傅的演示demo来学习

首先一样的,还是对想要序列化的类加上DataContract特性(同样支持Serializable特性),属性加上DataMember特性,然后再来看看序列化与反序列化流程:

这里还是要注意Type是否可控以及ReadObject()接受的内容是否可控,如果都可控则存在反序列化问题。来试验一下:

可以成功序列化与反序列化。那么我们要怎么攻击呢?


2.DataContractJsonSerializer反序列化安全问题

这里再介绍DataContractJsonSerializer的一个有趣用法,参考微软文档:

https://learn.microsoft.com/zh-cn/dotnet/framework/wcf/feature-details/stand-alone-json-serialization

也就是说,在序列化的json数据中可以加入一个__type键,后面可以指定命名空间+类名,看到这立马又给人一种Fastjson的既视感了,这个__type不就相当于@type吗?Ysoserial.net生成一个payload看看。

可以看见,这里指定

System.Security.Principal.WindowsPrincipal

并且给其m_identity赋值,这个详情可以看之前的WindowsPrincipal反序列化链分析

当Type可控的情况下,使用上述payload即可触发链子

还有几种即使Type不可控也能利用的情况,一种是使用了KnownType特性指定了WindowsPrincipal,来学习一下

如图,正常情况下,type不可控的话就没办法反序列化了,然而如果在Person类上方加一个特性

[KnownType(typeof(WindowsPrincipal))]

就可以正常反序列化WindowsPrincipal类的对象

此时可以成功RCE,但是正常开发者估计很少使用这玩意,就算用了大概率也不会指定WindowsPrincipal,除此之外还有一个方法可以指定KnownType:

最后一个参数可以指定List<Type>类型,其中可以存放Type,可以关注一下如果这个List可控,那么也相当于Type可控:

这个相比上面那种KnownType的用法来说,还是比较可能遇到。

除此之外Type不可控的情况下还有一种情况可以导致间接可控,就是利用

IDataContractSurrogate

这个机制甚至可以导致一些没有DataContract特性或Serializable特性的类参与序列化与反序列化

先写出三个类,Person类中的dog字段接受Dog类的对象,而Dog类又没有[DataContract]特性

然后这个DogSurrogated在我理解中算是后面用于存储Dog信息的一个中间人。

接下来写一个继承IDataContractSurrogate的类

在其中实现

GetDataContractType()

这个方法主要用于判断Type,如果是Dog,会自动返回

DogSurrogated Type

接着在GetObjectToSerialize方法中,会把Dog类的对象转化成XML格式的序列化数据

在GetDeserializedObject方法中,又会对XML格式的数据进行反序列化:

然后要怎么使用这个DogSurrogate类呢,看下图的演示

DataContractJsonSerializer

在上述构造方法调用的时候将其传入即可

来看看效果:

可以看到,原本应该不能正常序列化与反序列化的Dog类的对象,现在转化成了xml格式数据,后续也可以正常反序列化,如果目标在GetDeserializedObject中实现了别的反序列化操作,比如使用我们之前学习过的几个经典反序列化点,有很大概率会造成安全问题。

关于IDataContractSurrogate更详细的demo和分析可以参考Y4er师傅的文章

https://xz.aliyun.com/t/9601

HW专项行动小组
大师!教我打攻防
 最新文章