如果我的代码不对反序列化对象的状态或类做出任何假设,反序列化不受信任的数据是否安全,或者仅仅是反序列化的行为会导致不希望的操作?
(威胁模型:攻击者可以随意修改序列化的数据,但只能这么做)
如果我的代码不对反序列化对象的状态或类做出任何假设,反序列化不受信任的数据是否安全,或者仅仅是反序列化的行为会导致不希望的操作?
(威胁模型:攻击者可以随意修改序列化的数据,但只能这么做)
反序列化本身可能已经不安全了。可序列化的类可以定义一个readObject
方法(另见规范),当该类的对象将从流中反序列化时调用该方法。攻击者无法提供此代码,但使用精心设计的输入,她可以使用任何输入调用readObject
类路径上的任何此类方法。
可以readObject
实现为任意字节码注入打开大门。只需从流中读取一个字节数组并将其传递给ClassLoader.defineClass
and (有关前者和后者ClassLoader.resolveClass()
,请参见 javadoc )。我不知道这种实现的用途是什么,但这是可能的。
编写安全readObject
方法很难。直到最近,该readObject
方法HashMap
还包含以下几行。
int numBuckets = s.readInt();
table = new Entry[numBuckets];
这使得攻击者很容易用几十字节的序列化数据分配几千兆字节的内存,这将使您的系统立即崩溃OutOfMemoryError
。
当前的实现Hashtable
似乎仍然容易受到类似的攻击;它根据元素的数量和负载因子计算分配数组的大小,但是没有针对 中的不合理值的防范措施loadFactor
,因此我们可以轻松地请求为表中的每个元素分配十亿个槽。
修复漏洞HashMap
是作为更改的一部分完成的,以解决与基于哈希的映射相关的另一个安全问题。CVE-2012-2739描述了一种基于 CPU 消耗的拒绝服务攻击,方法是创建HashMap
具有非常多冲突键(即具有相同哈希值的不同键)的密钥。记录的攻击基于 URL 中的查询参数或 HTTP POST 数据中的键,但 a 的反序列化HashMap
也容易受到这种攻击。
为防止此类攻击而采取的保护措施主要集中在带有密钥的地图上。这足以防止基于 HTTP 的攻击,但很容易通过反序列化来规避,例如通过用一个(其 hashCode 也是可预测的)包装每个。Java 8 包含一个提案 ( JEP-180 ) 以进一步改进在面对许多冲突时的行为,它将保护扩展到所有实现的密钥类型,但仍然允许基于密钥的攻击。HashMap
String
String
ArrayList
HashMap
Comparable
ArrayList
这样做的结果是,攻击者有可能设计一个字节流,以便从该流中反序列化对象所需的 CPU 工作量随流的大小呈二次方增长。
通过控制反序列化过程的输入,攻击者可以触发任何readObject
反序列化方法的调用。这种方法理论上可以允许字节码注入。在实践中,这种方式当然很容易耗尽内存或 CPU 资源,从而导致拒绝服务攻击。针对此类漏洞审计您的系统非常困难:您必须检查的每个实现readObject
,包括第三方库和运行时库中的实现。