Hotdry.
ai-security

深度解析:为什么 BinaryFormatter 是 .NET 历史上最危险的组件

从 BinaryFormatter 的设计缺陷到 Json.Net 反序列化攻击,揭示 .NET 生态系统中最严重的反序列化风险类型,并提供完整的防护策略。

在 .NET 安全研究领域,反序列化漏洞始终占据着风险等级的顶峰。Microsoft 官方甚至用 " 调用 BinaryFormatter.Deserialize 等同于将有效负载解释为独立可执行文件并启动 " 来形象描述其危险程度 [1]。本文将深入解析 .NET 历史上最严重的反序列化威胁类型,从攻击向量到防护策略,为开发者提供完整的技术落地路径。

设计时代的产物:BinaryFormatter 的根本缺陷

BinaryFormatter 诞生于反序列化漏洞概念普及之前,其设计架构存在先天性的安全缺陷。Microsoft 官方明确指出,该类型 "带来风险,不建议将其用于数据处理"[1],并且 " 即使应用程序认为自己正在处理的数据是可信的,也应尽快停止使用 BinaryFormatter"[1]。

关键问题在于 BinaryFormatter 的无限制多态反序列化机制。当调用 Deserialize 方法时,它会在目标进程上下文中重建完整的对象图,包括执行构造函数、属性设置器和 ISerializable.GetObjectData 等方法。这相当于为攻击者提供了控制目标应用执行流的 "万能钥匙"。

Microsoft 对此的态度极为坚决:他们不会发布任何代码更新来修改此行为,认为这是 "设计使然"[1]。从 .NET 9 开始,BinaryFormatter 随机实现会在使用时直接抛出异常,彻底封禁该组件 [1]。

现实世界的攻击链:Json.Net 的隐蔽陷阱

虽然 BinaryFormatter 已被官方 "宣判死刑",但 .NET 生态中仍存在大量隐性的反序列化风险。Newtonsoft.Json 库中的 TypeNameHandling 配置就是典型代表。当开发者将 TypeNameHandling 设置为 ObjectsArraysAutoAll 时,就为攻击者敞开了大门。

核心攻击向量在于 TypeNameHandling 会将完整的类型信息(包括程序集名、版本等)嵌入到 JSON 数据中。反序列化时,Json.NET 会根据这些类型信息动态加载指定的类型,从而实现多态反序列化。

典型的攻击利用链通过 System.Diagnostics.Process 类的 Start 方法实现任意命令执行。攻击者构造的恶意 JSON 数据如下:

{
  "$type": "System.Diagnostics.Process, System",
  "StartInfo": {
    "$type": "System.Diagnostics.ProcessStartInfo, System",
    "FileName": "cmd.exe",
    "Arguments": "/c calc.exe"
  }
}

当使用 JsonConvert.DeserializeObject<dynamic>(maliciousJson, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }) 时,系统会自动实例化 Process 对象并调用其 Start 方法,从而执行恶意命令。

更隐蔽的攻击向量利用 WindowsIdentity 类的 ISerializable 实现。该类继承自 ClaimsIdentity,其 GetObjectData 方法允许攻击者控制序列化的完整流程 [2]。通过精心构造的序列化数据,攻击者可以触发目标应用执行任意 .NET 代码。

2024 年漏洞态势:持续演进的威胁

根据阿里云漏洞库的统计数据,2024 年 .NET 平台共披露了 15 个高危漏洞,其中反序列化相关漏洞占比显著 [3]。典型的 2024 年高危漏洞包括:

  • CVE-2024-21409:.NET Framework 远程代码执行漏洞
  • CVE-2024-21319:ASP.NET Core JWT 认证拒绝服务漏洞
  • CVE-2024-0057:X.509 证书链构建安全功能绕过漏洞

这些漏洞反映了攻击者从传统的反序列化攻击向身份认证绕过的策略转变。特别是在云原生架构下,攻击者更倾向于通过证书信任链的逻辑缺陷实现横向移动。

工程化防护:多层次防御策略

在 .NET 反序列化防护中,开发者需要建立多层次的安全防线。

第一道防线:序列化器选择 Microsoft 推荐使用 System.Text.Json 替代 Newtonsoft.Json,因为前者默认禁用类型名称处理,提供更好的安全基线。对于必须使用 JSON 序列化的场景,应始终将 TypeNameHandling 设置为 None

// 安全配置示例
var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    WriteIndented = true,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    TypeNameHandling = JsonTypeNameHandling.None  // 关键安全配置
};

第二道防线:序列化边界控制 对于无法替换的 BinaryFormatter 组件,可通过配置 SerializationBinder 限制可反序列化的类型:

var safeBinder = new CustomSerializationBinder();
var formatter = new BinaryFormatter();
formatter.Binder = safeBinder;

第三道防线:运行时监控 实施反序列化操作的代码审查和静态分析,识别潜在的高风险模式:

// 需要重点审查的代码模式
var json = "{\"$type\":\"System.Diagnostics.Process\"}";
var result = JsonConvert.DeserializeObject(json, settings);  // 高风险操作

检测与审计:自动化安全评估

建立自动化检测机制是防范反序列化漏洞的关键。开发者应集成 SAST(静态应用安全测试)工具,如 SonarQube 或 Checkmarx,配置 .NET 反序列化规则集。

动态检测方面,可以通过 WAF(Web 应用防火墙)规则检测常见的反序列化攻击载荷:

  • 检测 JSON 中的 $type 字段
  • 识别系统程序集引用(如 System.DiagnosticsSystem.Reflection
  • 监控异常的反序列化行为模式

对于审计历史代码,可通过以下 PowerShell 脚本快速识别潜在风险:

# 快速扫描 .NET 项目中的序列化风险点
Get-ChildItem -Recurse -Include "*.cs" | 
Select-String -Pattern "BinaryFormatter|JsonConvert.*TypeNameHandling|SoapFormatter" | 
Format-Table LineNumber, Path

未来防护趋势

随着 .NET 9 彻底废弃 BinaryFormatter,开发者面临的主要挑战是如何在遗留系统中安全地迁移序列化机制。企业级应用应制定详细的序列化技术栈升级计划,优先替换危险组件,并建立持续的漏洞监控机制。

在云原生环境下,推荐采用零信任架构的序列化策略:所有序列化操作都应被视为不受信任的输入处理,必须经过严格的类型验证和边界检查。通过将反序列化视为独立的信任域,可显著降低系统性安全风险。


[1] Microsoft Learn: 使用 BinaryFormatter 和相关类型时的反序列化风险 - https://learn.microsoft.com/zh-cn/dotnet/standard/serialization/binaryformatter-security-guide [2] CSDN: .NET 高级代码审计(第二课) Json.Net 反序列化漏洞 - https://m.blog.csdn.net/weixin_33901641/article/details/94688534
[3] 阿里云漏洞库: .NET 2024 年安全漏洞汇总 - https://avd.aliyun.com/product?page=0&prod=dotnet6-build

查看归档