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

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

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

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

代码注入

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

记忆力耗尽

编写安全的readObject方法很难。 直到最近 , HashMapreadObject方法包含以下行。

 int numBuckets = s.readInt(); table = new Entry[numBuckets]; 

这使得攻击者很容易只用几十个字节的序列化数据来分配几千兆字节的内存,这将使您的系统立即关闭OutOfMemoryError

目前 Hashtable 实施似乎仍然容易受到类似的攻击; 它根据元素的数量和加载因子计算分配数组的大小,但是在loadFactor没有防止不合理值的保护,所以我们可以轻松地为表中的每个元素分配10亿个槽。

CPU负载过大

修复HashMap中的漏洞是作为更改的一部分,以解决与基于散列的映射相关的另一个安全问题。 CVE-2012-2739描述了一种基于CPU消耗的拒绝服务攻击,它通过创建具有很多冲突密钥的HashMap (即具有相同散列值的不同密钥)。 记录的攻击基于URL中的查询参数或HTTP POST数据中的键,但HashMap反序列化也容易受到此攻击。

为防止此类攻击而放入HashMap的安全措施主要集中在使用String键的映射上。 这足以防止基于HTTP的攻击,但很容易通过反序列化来规避,例如通过使用ArrayList (其hashCode也是可预测的 )包装每个String 。 Java 8包含一个提议( JEP-180 ),以进一步改善HashMap在面对许多冲突时的行为,这将保护扩展到实现Comparable所有密钥类型,但仍然允许基于ArrayList密钥的攻击。

这样做的结果是,攻击者可以设计一个字节流,以便从该流中反序列化对象所花费的CPU工作量随着流的大小呈二次方式增长。

概要

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