BinaryFormatter 反序列化利用
字数 1314 2025-08-20 18:17:59

BinaryFormatter 反序列化利用技术详解

1. BinaryFormatter 基础

BinaryFormatter 是 .NET 中用于二进制序列化和反序列化的类,位于 System.Runtime.Serialization.Formatters.Binary 命名空间。

1.1 基本用法

[Serializable]
public class MyClass
{
    public int a;
    public int b;
}

// 序列化
void SerializeToFile(string filename, MyClass obj)
{
    FileStream fs = new FileStream(filename, FileMode.Create);
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(fs, obj);
}

// 反序列化
void DeserializeFromFile(string filename)
{
    FileStream fs = new FileStream(filename, FileMode.Open);
    BinaryFormatter formatter = new BinaryFormatter();
    MyClass obj = (MyClass)formatter.Deserialize(fs);
}

1.2 序列化生命周期

  1. 检查是否有代理选择器(SurrogateSelector),有则调用其处理方法
  2. 检查对象是否有 [Serializable] 特性,没有则抛出异常
  3. 检查是否实现 ISerializable 接口,实现则调用其 GetObjectData 方法
  4. 否则使用默认策略序列化所有未标记 [NonSerialized] 的字段

2. ISerializable 接口

自定义序列化可通过实现 ISerializable 接口来控制:

[Serializable]
public class MyClass : ISerializable
{
    public int n1;
    public string str;

    // 必须实现的构造函数
    protected MyClass(SerializationInfo info, StreamingContext context)
    {
        n1 = info.GetInt32("i");
        str = info.GetString("s");
    }

    // ISerializable 方法
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("i", n1);
        info.AddValue("s", str);
    }
}

3. 序列化事件

.NET 提供了四个序列化事件特性:

特性 调用时机 典型用途
OnDeserializingAttribute 反序列化之前 初始化可选字段默认值
OnDeserializedAttribute 反序列化之后 根据其他字段修改可选字段
OnSerializingAttribute 序列化之前 准备序列化,创建数据结构
OnSerializedAttribute 序列化之后 记录序列化事件

4. 序列化控制机制

4.1 SurrogateSelector (代理选择器)

代理选择器可以接管序列化/反序列化过程:

class MySurrogate : ISerializationSurrogate
{
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
    {
        // 自定义序列化逻辑
    }

    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        // 自定义反序列化逻辑
        return new MyClass();
    }
}

// 使用代理
SurrogateSelector ss = new SurrogateSelector();
ss.AddSurrogate(typeof(MyClass), new StreamingContext(), new MySurrogate());
formatter.SurrogateSelector = ss;

4.2 SerializationBinder (序列化绑定器)

用于控制反序列化时的类型绑定,可用于安全防护:

class SafeBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        if (typeName == "System.Data.DataSet")
            throw new Exception("危险类型禁止反序列化");
        return Type.GetType($"{typeName}, {assemblyName}");
    }
}

// 使用绑定器
formatter.Binder = new SafeBinder();

5. 安全风险与绕过技术

5.1 危险类型

以下类型特别危险:

  • System.Data.DataSet
  • System.Windows.Forms.AxHost
  • System.Configuration.Install.AssemblyInstaller

5.2 SerializationBinder 绕过技术

5.2.1 空白字符绕过

string typeName = "\nSystem.Data.DataSet,\nSystem.Data";
Type.GetType(typeName); // 仍然能解析

5.2.2 前导点号

string typeName = ".System.Data.DataSet, System.Data";

5.2.3 程序集引号

string typeName = "System.Data.DataSet, \"System.Data\"";

5.2.4 大小写不敏感

string typeName = "System.Data.DataSet, system.data";

5.2.5 属性顺序任意

string typeName = "System.Data.DataSet, System.Data, PublicKeyToken=b77a5c561934e089, Version=4.0.0.0";

5.3 加固建议

  1. 避免使用 BinaryFormatter,改用 JsonSerializerXmlSerializer
  2. 如果必须使用,实现严格的 SerializationBinder
  3. 检查并清理输入中的特殊字符
  4. 使用白名单而非黑名单

6. 替代方案

以下序列化程序同样危险,应避免使用:

  • SoapFormatter
  • LosFormatter
  • NetDataContractSerializer
  • ObjectStateFormatter

7. 参考资源

  1. Microsoft 官方文档 - 自定义序列化
  2. .NET 反序列化漏洞详解
  3. 绕过 .NET 序列化绑定器
  4. .NET 反序列化入门
BinaryFormatter 反序列化利用技术详解 1. BinaryFormatter 基础 BinaryFormatter 是 .NET 中用于二进制序列化和反序列化的类,位于 System.Runtime.Serialization.Formatters.Binary 命名空间。 1.1 基本用法 1.2 序列化生命周期 检查是否有代理选择器(SurrogateSelector),有则调用其处理方法 检查对象是否有 [Serializable] 特性,没有则抛出异常 检查是否实现 ISerializable 接口,实现则调用其 GetObjectData 方法 否则使用默认策略序列化所有未标记 [NonSerialized] 的字段 2. ISerializable 接口 自定义序列化可通过实现 ISerializable 接口来控制: 3. 序列化事件 .NET 提供了四个序列化事件特性: | 特性 | 调用时机 | 典型用途 | |------|----------|----------| | OnDeserializingAttribute | 反序列化之前 | 初始化可选字段默认值 | | OnDeserializedAttribute | 反序列化之后 | 根据其他字段修改可选字段 | | OnSerializingAttribute | 序列化之前 | 准备序列化,创建数据结构 | | OnSerializedAttribute | 序列化之后 | 记录序列化事件 | 4. 序列化控制机制 4.1 SurrogateSelector (代理选择器) 代理选择器可以接管序列化/反序列化过程: 4.2 SerializationBinder (序列化绑定器) 用于控制反序列化时的类型绑定,可用于安全防护: 5. 安全风险与绕过技术 5.1 危险类型 以下类型特别危险: System.Data.DataSet System.Windows.Forms.AxHost System.Configuration.Install.AssemblyInstaller 5.2 SerializationBinder 绕过技术 5.2.1 空白字符绕过 5.2.2 前导点号 5.2.3 程序集引号 5.2.4 大小写不敏感 5.2.5 属性顺序任意 5.3 加固建议 避免使用 BinaryFormatter ,改用 JsonSerializer 或 XmlSerializer 如果必须使用,实现严格的 SerializationBinder 检查并清理输入中的特殊字符 使用白名单而非黑名单 6. 替代方案 以下序列化程序同样危险,应避免使用: SoapFormatter LosFormatter NetDataContractSerializer ObjectStateFormatter 7. 参考资源 Microsoft 官方文档 - 自定义序列化 .NET 反序列化漏洞详解 绕过 .NET 序列化绑定器 .NET 反序列化入门