在Java中反序列化不受信任的数据有什么安全影响?

在Java中反序列化不受信任的数据有什么安全影响?,java,security,serialization,Java,Security,Serialization,如果我的代码不对反序列化对象的状态或类进行假设,反序列化不受信任的数据是否安全,或者仅仅反序列化的行为是否会导致不希望的操作 (威胁模型:攻击者可以自由修改序列化数据,但他只能这样做)反序列化本身可能已经不安全。可序列化类可以定义readObject方法(另请参见),当此类的对象将从流中反序列化时调用该方法。攻击者无法提供此代码,但通过使用精心编制的输入,她可以使用任何输入调用类路径上的任何此类readObject方法 代码注入 可以创建一个readObject实现,为任意字节码注入打开大门。只

如果我的代码不对反序列化对象的状态或类进行假设,反序列化不受信任的数据是否安全,或者仅仅反序列化的行为是否会导致不希望的操作


(威胁模型:攻击者可以自由修改序列化数据,但他只能这样做)

反序列化本身可能已经不安全。可序列化类可以定义
readObject
方法(另请参见),当此类的对象将从流中反序列化时调用该方法。攻击者无法提供此代码,但通过使用精心编制的输入,她可以使用任何输入调用类路径上的任何此类
readObject
方法

代码注入 可以创建一个
readObject
实现,为任意字节码注入打开大门。只需从流中读取一个字节数组,并将其传递给
ClassLoader.defineClass
ClassLoader.resolveClass()
(有关和,请参阅javadoc)。我不知道这样一个实现的用途是什么,但这是可能的

内存耗尽 编写安全的
readObject
方法很难。直到
HashMap
readObject
方法包含以下行

int numBuckets = s.readInt();
table = new Entry[numBuckets];
这使得攻击者很容易用几十字节的序列化数据分配几GB的内存,这将使您的系统在短时间内发生
OutOfMemoryError

哈希表的似乎仍然容易受到类似的攻击;它根据元素的数量和负载因子计算分配的数组的大小,但是在
负载因子中没有防止不合理值的措施,因此我们可以很容易地请求为表中的每个元素分配10亿个插槽

CPU负载过大 修复
HashMap
中的漏洞是为了解决与基于哈希的映射相关的另一个安全问题而进行的更改的一部分。描述了一种基于CPU消耗的拒绝服务攻击,该攻击通过创建具有大量冲突键(即具有相同哈希值的不同键)的
HashMap
。记录在案的攻击基于URL中的查询参数或HTTP POST数据中的键,但是
哈希映射的反序列化也容易受到此攻击

放入
HashMap
以防止这种类型的攻击的对象集中在带有
String
键的映射上。这足以防止基于HTTP的攻击,但可以通过反序列化轻松规避,例如,通过使用
ArrayList
包装每个
String
(其hashCode也为空)。Java 8包含了一个建议()以进一步改进
HashMap
在面对许多冲突时的行为,该建议将保护扩展到实现
Comparable
的所有密钥类型,但仍然允许基于
ArrayList
密钥的攻击

这样做的结果是,攻击者可以设计字节流,从而使从该流反序列化对象所需的CPU工作随流的大小呈二次增长

总结
通过控制反序列化过程的输入,攻击者可以触发任何
readObject
反序列化方法的调用。理论上,这种方法允许字节码注入。实际上,通过这种方式很容易耗尽内存或CPU资源,从而导致拒绝服务攻击。针对此类漏洞审计您的系统非常困难:您必须检查
readObject
的每个实现,包括第三方库和运行库中的实现。

如果序列化数据包含个人信息或银行信息,则绝对(存在安全风险)。这就是加密的目的。如果不对代码进行任何假设,很难说出这一点。在一些代码库中是这样的,而在其他代码库中我认为不会这样。公共和私人变量的意义在于保证某些状态是不可能的。在反序列化不受信任的数据时,您将失去此保证。问题是你的代码是否有这样的保证,它们有多重要这个问题是关于反序列化而不是序列化的危险。我理解后者,通信确实是加密的。我提到反序列化。和不受信任的源。对于初学者来说,如果程序的正确性取决于单例的单一性(甚至类似于内部实例),则存在潜在的风险,除非您显式管理返回的对象。@meriton问题是,这是一个格式错误的要求。我可以创建一个类,这样任何反序列化都不会引起任何问题。我可以再找一个会引起问题的。因此,对类一无所知,您不能假设这是安全的+1我认为这里的故事的寓意是,序列化对象不是接受输入的正确方式。