在Java中反序列化不受信任的数据有什么安全影响? [英] What is the security impact of deserializing untrusted data in Java?

查看:337
本文介绍了在Java中反序列化不受信任的数据有什么安全影响?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is it safe to deserialize untrusted data, provided my code makes no assumptions about the state or class of the deserialized object, or can the mere act of deserializing cause undesired operation?

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

(Threat model: The attacker may freely modify the serialized data, but that's all he can do)

推荐答案

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

Deserialization itself can already be unsafe. A serializable class may define a readObject method (see also the specification), which is called when an object of this class is going to be deserialized from the stream. The attacker cannot provide this code, but using a crafted input she can invoke any such readObject method that is on your classpath, with any input.

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

It is possible to make a readObject implementation that opens the door to arbitrary bytecode injection. Simply read a byte array from the stream and pass it to ClassLoader.defineClass and ClassLoader.resolveClass() (see the javadoc for the former and the later). I don't know what the use of such an implementation would be, but it is possible.

编写安全的 readObject 方法很难。直至最近 HashMap readObject 方法包含以下几行。

Writing secure readObject methods is hard. Up until somewhat recently the readObject method of HashMap contained the following lines.

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

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

This makes it very easy for an attacker to allocate several gigabytes of memory with just a few dozen bytes of serialized data, which will have your system down with an OutOfMemoryError in no time.

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

The current implementation of Hashtable seems to still be vulnerable to a similar attack; it computes the size of the allocated array based on the number of elements and the load factor, but there is no guard in place against unreasonable values in loadFactor, so we can easily request a billion slots be allocated for each element in the table.

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

Fixing the vulnerability in HashMap was done as part of changes to address another security issue related to hash-based maps. CVE-2012-2739 describes a denial-of-servic attack based on CPU consumption by creating a HashMap with very many colliding keys (i.e. distinct keys with the same hash value). The documented attacks are based on query parameters in URLs or keys in HTTP POST data, but deserialization of a HashMap is also vulnerable to this attack.

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

The safeguards that were put into HashMap to prevent this type of attack are focussed on maps with String keys. This is adequate to prevent the HTTP-based attacks, but is easily circumvented with deserialization, e.g. by wrapping each String with an ArrayList (whose hashCode is also predictable). Java 8 includes a proposal (JEP-180) to further improve the behaviour of HashMap in the face of many collisions, which extends the protection to all key types that implements Comparable, but that still allows an attack based on ArrayList keys.

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

The upshot of this is that is possible for the attacker to engineer a byte streams such that the CPU effort it takes to deserialize an object from this stream grows quadratically with the size of the stream.

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

By controlling the input to the deserialization process an attacker can trigger the invocation of any readObject deserialization-method. It is theoretically possible for such a method to allow bytecode injection. In practice it is certainly possible to easily exhaust memory or CPU resources this way, resulting in denial-of-service attacks. Auditing your system against such vulnerabilities is very difficult: you have to check every implementation of readObject, including those in third-party libraries and the runtime library.

这篇关于在Java中反序列化不受信任的数据有什么安全影响?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆