10.JavaScriptSerializer反序列化点

2024-10-25 13:22   广东  

1.JavaScriptSerializer基础使用

这也是一个用于json序列化与反序列化的类,学习一下使用。先写一个用于测试的类,注意这个类可以不用打上Serializable特性

序列化与反序列化流程如下:

运行一下代码。可以看到,序列化后产生的数据是

{"Name":"test"}

并且在反序列化过程中,会依次触发Person类的构造方法,以及对应属性的set方法。推测JavaScriptSerializer的底层是用反射实现的


2.JavaScriptSerializer反序列化安全问题

既然可能是用反射实现,那感觉危害程度会比较高。那么它有没有类似__type或者@type这样的特性去指定反序列化的类呢?在文档里下面几条有一个

SimpleTypeResolver

微软专门给了警告说它可能会造成反序列化问题,可能这就是我们要找的东西了

看看微软给出的不安全代码演示嗷,可以看到在调用JavaScriptSerializer构造方法的时候,传入了SimpleTypeResolver类的对象,后续反序列化的时候还是个泛型

第二个不安全代码演示如下:

虽然没有使用Deserialize泛型,但是使用了SimpleTypeResolver,仍然存在反序列化漏洞。我们来试试看,我们也加一个SimpleTypeResolver

注意此时生成的数据:

{"__type":"JavaScriptDeserialize.Person, ConsoleApp3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Name":"test"}

好家伙,__type这么指定是吧,你比fastjson还NB啊。那我们搓链子其实很容易,直接按格式做一个恶意ObjectDataProvider类的对象即可

运行,成功RCE

这个过程都很好理解,还是从代码上去看看为什么。

跟进BasicDeserialize(),这里把传参送到JavaScriptObjectDeserializer类构造方法里包装了一下,然后调用这个类的DeserializeInternal方法

构造方法主要是做一些类的初始化(重要的序列化数据被赋值给_s属性了)

继续跟进DeserializeInternal()方法,这里判断json数据里是否有__type键,有则进入ConvertObjectToType方法

又进入ConvertObjectToTypeMain方法

这里会把o(前面包含__type信息的dictionary变量)传入ConvertObjectToTypeInternal方法

跟进ConvertObjectToTypeInternal,又把dictionary传入ConvertDictionaryToObject方法

这个方法里有三步比较重要,先从dictionary里取出__type的值,然后赋值给obj2.接着给obj2赋值给text,再接着把text传入ResolveType()方法

而这个ResolveType()方法实际上是SimpleTypeResolver类中的同名方法:

可以看到,这个方法把传入字符进一步传入GetType()方法,也就是说这里直接获取到我们传入的__type的Type对象,也即此时的type2

再往后,这里对type2调用Activator.CreateInstance()方法,即可创造目标类的对象

因此,目标使用SimpleTypeResolver这个条件非常关键,或者如果目标自实现了TypeResolver,且其ResolveType()写法也是直接Type.GetType()的话,也有漏洞。实战审计中主要关注是否有类似下面这样的代码:

JavaScriptSerializer()构造方法里传入

new SimpleTypeResolver()

且Deserialize()接受的json数据可控,则存在反序列化漏洞。然后如果你看到Deserialize()方法里的type传参不可控,比如下面这样:

别担心,这不影响我们进行反序列化攻击


3.参考

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

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