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 序列化生命周期
- 检查是否有代理选择器(SurrogateSelector),有则调用其处理方法
- 检查对象是否有
[Serializable]特性,没有则抛出异常 - 检查是否实现
ISerializable接口,实现则调用其GetObjectData方法 - 否则使用默认策略序列化所有未标记
[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.DataSetSystem.Windows.Forms.AxHostSystem.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 加固建议
- 避免使用
BinaryFormatter,改用JsonSerializer或XmlSerializer - 如果必须使用,实现严格的
SerializationBinder - 检查并清理输入中的特殊字符
- 使用白名单而非黑名单
6. 替代方案
以下序列化程序同样危险,应避免使用:
SoapFormatterLosFormatterNetDataContractSerializerObjectStateFormatter