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

Posted

技术标签:

【中文标题】在 Java 中反序列化不受信任的数据有啥安全影响?【英文标题】:What is the security impact of deserializing untrusted data in Java?在 Java 中反序列化不受信任的数据有什么安全影响? 【发布时间】:2013-10-03 23:15:54 【问题描述】:

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

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

【问题讨论】:

如果序列化数据中包含个人信息,或者银行信息,那么绝对(存在安全风险)。这就是加密的用途。如果不对代码做出任何假设,就很难说出这一点。在某些代码库中它会是,而其他我认为不会。公共和私有变量的重点是保证某些状态是不可能的。反序列化不受信任的数据时,您将失去此保证。问题是你的代码是否有这样的保证,以及它们的重要性 这个问题是关于反序列化而不是序列化的危险。我理解后者,通信确实是加密的。 我提到了反序列化。以及不受信任的来源。 对于初学者来说,如果你的程序的正确性依赖于单例的单一性(或者甚至像实习实例这样的东西),除非你明确地管理返回的对象,否则存在潜在的风险。 @meriton 关键是,这是一个格式错误的要求。我可以创建一个类,这样任何反序列化都不会导致任何问题。我可以再做一个会引起问题的。所以对课程一无所知,你不能认为这是安全的 【参考方案1】:

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

代码注入

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

内存耗尽

编写安全的readObject 方法很难。直到somewhat recently readObject 的方法 HashMap 包含以下行。

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

这使得攻击者可以很容易地用几十字节的序列化数据分配几千兆字节的内存,这将使您的系统立即崩溃并显示OutOfMemoryError

Hashtable 的current implementation 似乎仍然容易受到类似攻击;它根据元素的数量和负载因子计算分配数组的大小,但没有针对loadFactor 中不合理的值的防范措施,因此我们可以轻松地请求为表中的每个元素分配十亿个槽.

CPU 负载过大

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

为防止此类攻击而放入HashMap 的safeguards 集中在带有String 键的地图上。这足以防止基于 HTTP 的攻击,但很容易通过反序列化来规避,例如通过用ArrayList 包装每个String(其hashCode 也是predictable)。 Java 8 包含一个提案 (JEP-180) 以进一步改进 HashMap 在面对许多冲突时的行为,它将保护扩展到实现 Comparable 的所有密钥类型,但仍然允许基于 @987654351 的攻击@键。

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

总结

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

【讨论】:

+1 我认为这个故事的寓意是,序列化对象不是接受输入的正确方式。

以上是关于在 Java 中反序列化不受信任的数据有啥安全影响?的主要内容,如果未能解决你的问题,请参考以下文章

自己做的ssl证书和ca证书有啥区别

需要使用 myfaces 1.1 针对 Wildfly 10 反序列化不受信任数据的示例代码

将不受信任的java代码限制为单个线程[重复]

如何将浏览器中不受信任的证书手动设置为信任

安全执行不受信任的 Haskell 代码

getJSON() 是不是可以安全地调用不受信任的 URL?