rotabor Asked:2024-07-29 18:13:54 +0800 CST2024-07-29 18:13:54 +0800 CST 2024-07-29 18:13:54 +0800 CST BinaryFormatter 有哪些危险? 772 有人可以对以二进制形式序列化数据的危险给出合理的解释,或者参考一个好的解释吗?“使用 BinaryFormatter 和相关类型的反序列化风险”中给出的“它本质上是危险的”或“它无法安全处理”之类的论点并没有说服我。 .net 3 个回答 Voted Best Answer aepot 2024-07-29T21:44:13+08:002024-07-29T21:44:13+08:00 关键是,反序列化时,格式化程序可以在内存中创建任何类型,绝对是任何类型。例如,如果您将 lib 与您的类型放在一起,然后将序列化对象提供给格式化程序,它只会运行您的代码,而不知道正在等待某些数据的应用程序。 格式化程序不考虑类成员的可见性,甚至不像使用new.它创建的实例基本上是这样的: var obj = FormatterServices.GetUninitializedObject(typeof(MyType)); 也就是说,如果构造函数在创建实例时对对象状态的完整性有任何保护,则可以通过这种方式轻松绕过。嗯,那就有足够的想象力了。 是的,格式化程序在创建对象快照并将其写入磁盘或通过网络传输方面快速可靠,但您应该非常小心安全细微差别。 事实上,没有人禁止使用它,为了你的健康使用它,但出于某种原因,它被从主 .NET 代码中取出到一个外部包中,并在项目文件中用密钥覆盖。因此,您必须手动安装和解锁它,这是对此的确认,因为您毕竟决定使用它,您了解自己在做什么。 在某些基础设施中,格式化程序是在集群中的节点之间尽可能快速、方便地传输数据的最佳方式,例如通过 AMQP。也就是说,在不受外部影响的环境中,可以使用它,并且可以使用它。至少,因为在使用复杂对象时没有序列化器会提供相同的性能,尽管在某些地方,JsonSerializer最新(8+)dotnets中的相同序列化器由于代码生成而开始迎头赶上。 VladD 2024-07-30T06:28:51+08:002024-07-30T06:28:51+08:00 看看出了什么问题。 BinaryFormatter 有两个大问题:它没有实现构造函数(可以验证数据),而且它是多态的。最后一个问题特别危险,因为它很容易导致攻击者强制 BinaryFormatter 创建他们选择的对象。例如如下。 让攻击者有机会自己制作用于反序列化的二进制数据。假设攻击者想要创建一个类型为 的对象X。如果反序列化不同类型的对象Y,攻击者就可以将所需类型的对象插入到序列化数据中X。类型转换将失败,但类型对象X仍将被创建。 (如果攻击者不想进行转换的麻烦,他可以找到一个Y具有 type field 的可序列化类型object,并将该类的实例放置X在该字段中。) 创建某些对象有什么危险?毕竟,攻击者并不能控制这个对象?事实上,.NET 中有许多类,如果它们恰好出现在您的进程中,那么它们可能会很危险。例如, Why so Serial项目致力于研究哪些类是危险的,它提供了危险类的示例(并且可以创建它们的反序列化表示)。 最简单的例子是旧类TempObjectCollection,它在其终结器中删除一组名称存储在对象字段中的文件。如您所知,对象字段由攻击者控制,他可以在那里“填充”任何文件名。 此外,此类类很可能在标准 .NET 库中找不到,而是在流行的 nuget 包中找到,或者只是受攻击程序的作者无意中编写的。 但也许我们可以通过将 BinaryFormatter 限制为反序列化类的“白名单”来保存它?不幸的是,这也无济于事,原因有两个。 第一个原因是几乎所有使用 BinaryFormatter 的代码都来自多态性。这段代码将停止工作。 第二个原因是反序列化绕过了构造函数中值的验证,也是非常危险的。例如,即使您使用数字/字符串键反序列化数组和字典,攻击者仍然可以损坏您的对象:还有Dictionary<K, V>许多字段可能导致内存溢出等问题。 编写依据: 回复 en.SO 官方公告 BinaryFormatter 已弃用 关于在 GitHub 上保存 BinaryFormatter 的可能性的讨论 项目YSoSerial.NET,致力于利用 BinaryFormatter (以及其他序列化器)的问题 Glebka 2024-07-30T18:23:00+08:002024-07-30T18:23:00+08:00 简而言之 -BinaryFormatter不同版本的 .NET 之间不兼容。 它也已经过时,并且在最新版本的 .net 中没有更新 如果在一个版本中用它序列化数据,然后更新项目中的.net版本,就会出现反序列化错误。或者如果客户端和服务器上的 .net 版本不同
关键是,反序列化时,格式化程序可以在内存中创建任何类型,绝对是任何类型。例如,如果您将 lib 与您的类型放在一起,然后将序列化对象提供给格式化程序,它只会运行您的代码,而不知道正在等待某些数据的应用程序。
格式化程序不考虑类成员的可见性,甚至不像使用
new
.它创建的实例基本上是这样的:也就是说,如果构造函数在创建实例时对对象状态的完整性有任何保护,则可以通过这种方式轻松绕过。嗯,那就有足够的想象力了。
是的,格式化程序在创建对象快照并将其写入磁盘或通过网络传输方面快速可靠,但您应该非常小心安全细微差别。
事实上,没有人禁止使用它,为了你的健康使用它,但出于某种原因,它被从主 .NET 代码中取出到一个外部包中,并在项目文件中用密钥覆盖。因此,您必须手动安装和解锁它,这是对此的确认,因为您毕竟决定使用它,您了解自己在做什么。
在某些基础设施中,格式化程序是在集群中的节点之间尽可能快速、方便地传输数据的最佳方式,例如通过 AMQP。也就是说,在不受外部影响的环境中,可以使用它,并且可以使用它。至少,因为在使用复杂对象时没有序列化器会提供相同的性能,尽管在某些地方,
JsonSerializer
最新(8+)dotnets中的相同序列化器由于代码生成而开始迎头赶上。看看出了什么问题。
BinaryFormatter 有两个大问题:它没有实现构造函数(可以验证数据),而且它是多态的。最后一个问题特别危险,因为它很容易导致攻击者强制 BinaryFormatter 创建他们选择的对象。例如如下。
让攻击者有机会自己制作用于反序列化的二进制数据。假设攻击者想要创建一个类型为 的对象
X
。如果反序列化不同类型的对象Y
,攻击者就可以将所需类型的对象插入到序列化数据中X
。类型转换将失败,但类型对象X
仍将被创建。(如果攻击者不想进行转换的麻烦,他可以找到一个
Y
具有 type field 的可序列化类型object
,并将该类的实例放置X
在该字段中。)创建某些对象有什么危险?毕竟,攻击者并不能控制这个对象?事实上,.NET 中有许多类,如果它们恰好出现在您的进程中,那么它们可能会很危险。例如, Why so Serial项目致力于研究哪些类是危险的,它提供了危险类的示例(并且可以创建它们的反序列化表示)。
最简单的例子是旧类
TempObjectCollection
,它在其终结器中删除一组名称存储在对象字段中的文件。如您所知,对象字段由攻击者控制,他可以在那里“填充”任何文件名。此外,此类类很可能在标准 .NET 库中找不到,而是在流行的 nuget 包中找到,或者只是受攻击程序的作者无意中编写的。
但也许我们可以通过将 BinaryFormatter 限制为反序列化类的“白名单”来保存它?不幸的是,这也无济于事,原因有两个。
第一个原因是几乎所有使用 BinaryFormatter 的代码都来自多态性。这段代码将停止工作。
第二个原因是反序列化绕过了构造函数中值的验证,也是非常危险的。例如,即使您使用数字/字符串键反序列化数组和字典,攻击者仍然可以损坏您的对象:还有
Dictionary<K, V>
许多字段可能导致内存溢出等问题。编写依据:
简而言之 -
BinaryFormatter
不同版本的 .NET 之间不兼容。它也已经过时,并且在最新版本的 .net 中没有更新
如果在一个版本中用它序列化数据,然后更新项目中的.net版本,就会出现反序列化错误。或者如果客户端和服务器上的 .net 版本不同