flawopen.com/不安全的反序列化/.NET BinaryFormatter 安全
.NET 的 BinaryFormatter 安全吗?
Microsoft 指出 BinaryFormatter 不安全且无法变安全,并建议停止使用,即使应用认为输入可信也一样。在 .NET 9 中,API 类型仍然存在,但内置实现每次调用都会抛出 PlatformNotSupportedException;旧版运行时和不受支持的兼容包仍保留原有风险。
// 不要反序列化跨越信任边界的数据。 using System.IO; using System.Runtime.Serialization.Formatters.Binary; public static class LegacyReader { public static object Deserialize(Stream input) => new BinaryFormatter().Deserialize(input); } // 同样应移除这些无限制多态序列化器: SoapFormatter NetDataContractSerializer LosFormatter ObjectStateFormatter // ASP.NET ViewState 内部使用 // SerializationBinder 不能让这些格式变安全。
// 数据形状由应用代码声明。 // Nullable reference types make the DTO contract explicit. #nullable enable using System; using System.IO; using System.Text.Json; public sealed record MyDto(int Id, string Name); public static class DtoReader { public static MyDto Parse(ReadOnlySpan<byte> json) { // 限制输入大小并验证应用规则。 if (json.Length > 65_536) throw new InvalidDataException(); MyDto? value = JsonSerializer.Deserialize<MyDto>(json); if (value is null || value.Id <= 0 || string.IsNullOrWhiteSpace(value.Name) || value.Name.Length > 100) throw new InvalidDataException(); return value; } } // 对旧 NRBF 文件用 NrbfDecoder 检查 // 记录,再将允许的值映射到 DTO。 // 不要重建任意运行时类型。
BinaryFormatter 为什么危险
BinaryFormatter.Deserialize 会从数据流重建对象图,攻击者控制的数据可能影响程序控制流。Microsoft 警告其可能造成拒绝服务、信息泄露和远程代码执行。核心问题是无限制的多态反序列化:序列化数据可以影响程序处理哪些类型和对象状态。没有任何 formatter 开关能把它变成安全的不可信字节解析器。
风险并不局限于公开 HTTP 接口。文件、缓存、队列、数据库记录、桌面客户端消息和云同步状态以后都可能受攻击者影响。追踪字节如何进入并经过系统;“数据是我们写的”或“数据是内部的”不能作为永久信任标签。
SerializationBinder 为什么不够
自定义 SerializationBinder 可以限制 formatter 尝试解析的类型,但 Microsoft 明确指出,binder 或其他配置开关无法缓解拒绝服务攻击,对其他攻击类型也可能不足。Binder 不能替代迁移;在移除 BinaryFormatter 之前,不要接受不可信输入。
查找遗留调用与相关路径
在源代码、项目引用和运行时配置中搜索 BinaryFormatter、IFormatter、SoapFormatter、NetDataContractSerializer、LosFormatter 和 ObjectStateFormatter。检查会话状态提供程序、缓存适配器、队列消费者、文件导入导出和旧 ASP.NET Web Forms 路径。ViewState 通常由消息认证码(MAC)保护;保持该保护开启并保护 machine key。MAC 并不能让通用 BinaryFormatter 反序列化变安全。
按数据格式和运行时版本制定迁移计划
新数据应根据格式和兼容需求选择显式契约,例如 System.Text.Json、DataContractSerializer、MessagePack 或 protobuf-net;没有直接替代品。若必须保留旧 NRBF 文件,.NET 9 的 NrbfDecoder 可在不实例化编码应用类型的情况下解码记录。验证解码后的结构,并只将预期值映射到应用 DTO。另行查看 WinForms/WPF 对资源、剪贴板和拖放场景的迁移指南。
常见问题
Microsoft 建议即使数据看似可信也迁移,因为存储、缓存、文件、同步和下游服务都可能跨越信任边界。查明谁能写入每个来源,并停止使用 BinaryFormatter,不要依赖信任假设。
在 .NET 9 中,API 类型仍存在,但内置实现始终抛出 PlatformNotSupportedException,旧兼容开关也无效。升级前审计调用并完成迁移。不受支持的兼容包会恢复有风险的实现,并非安全修复。
Json.NET 默认将 TypeNameHandling 设为 None,不会让 payload 元数据选择任意 CLR 类型。不要对不可信输入启用其他值。若需要多态,应使用应用控制的严格允许列表并遵循库的安全指南。参见TypeNameHandling 安全吗?
来源与参考资料
- Microsoft Learn — BinaryFormatter security guide
- Microsoft Learn — BinaryFormatter migration guide
- Microsoft Learn — Choose a BinaryFormatter replacement
- Microsoft Learn — Safely read NRBF payloads with NrbfDecoder
- Microsoft Learn — SYSLIB0011
- Microsoft Learn — ASP.NET ViewState MAC
- CWE-502 — Deserialization of Untrusted Data
- Is Json.NET TypeNameHandling safe?