Java序列化漏洞威胁着上百万的应用

https://dzone.com/articles/java-serialization-vulnerability-threatens-million

一个在Java环境中广泛传播的漏洞使得数千的商务信息被暴露。尽管这个漏洞没有一个酷炫的名字——比如心血(Heartbleed)、破壳(Shellshock)或者POODLE——它却被指出能让黑客通过互联网进行攻击。然而,目前没有一种方法能保护所有的应用。这意味着需要团队们花费很长一段时间来寻找和修复这个漏洞的变体。

Contrast安全公司(以下简称Contrast)开发了一种使用我们的专利,强大的应用安全构建平台,快速准确的修复了这个问题。Contrast可以使用我们的IAST方法来分辨出这个问题。它也可以通过使用我们的RASP功能来立即修复这个问题或者生成安全警报,并且不必重编码。在服务器上安装一个Contrast客户端就可以标记出这个服务器上所有存在问题的Jaca应用程序。

如果你想了解更多关于Jacaranda序列化漏洞的细节,请继续往下读。序列化是一种让开发者将数据结构转化成一串比特流来存储或者发送的方法。反序列化则是一个相反的过程,将接收后的数据转换为特定数据结构。早在2010年之前,序列化就已经开始出现安全问题。完整安全问题历史记录详见http://www.ibm.com/developerworks/library/se-lookahead 。最近,在一系列不同的Java环境中都发现了漏洞——遗憾的是,这可能是唯一一种能让安全问题得到重视的方式。

这些漏洞非常严重,可以被利用来实现执行整个远程命令——任何程序的主机将被接管,只要这个程序接受了序列化对象。

在Java中,读取一个序列化流中的SetBit是非常简单的:

ObjectInputStream in = new ObjectInputStream( inputStream );     
return (Data)in.readObject();

但问题在于,你不知道在解码之前你究竟反序列化了什么。所以一个攻击者可以序列化一串恶意对象,并把它们发送到你的程序。一旦你调用readObject(),一切就都已经迟了。有时候,它就像XXE漏洞,攻击者可以使用恶意文件格式,在XML解析的时候发起攻击。不过,在我们的例子中,没有一个简单的方法来终止解析过程。

现在所需的是一种可以运行序列化,但不会让攻击者有机会创建任意类的实例。比如:

List<Class<?>> safeClasses = Arrays.asList( BitSet.class, ArrayList.class );
Data d2 = safeReadObject( Data.class, safeClasses, new FileInputStream( f ) );

这允许开发者指定返回类型和希望在序列化对象中出现的类清单,一旦出现没有被授权的,我们将抛出一个安全异常并阻止请求。结果表明实现这个并不难。我们只需要重载一下ObjectInputStream的执行就可以了。

以下是是一种替代调用readObject的方法:

@SuppressWarnings("unchecked")
    public static <T> T safeReadObject(Class<?> type, List<Class<?>> safeClasses, InputStream in ) throws IOException, ClassNotFoundException {
        return (T) new ObjectInputStream(in) {
            protected Class<?> resolveClass(ObjectStreamClass d) throws IOException, ClassNotFoundException {
                Class<?> clazz = super.resolveClass(d);
                if (clazz.isArray()
                    || clazz.isPrimitive()
                    || clazz.equals(type)
                    || clazz.equals(String.class)
                    || Number.class.isAssignableFrom(clazz)
                    || safeClasses.contains(clazz)) return clazz;
                throw new SecurityException("Attempt to deserialize unauthorized " + clazz);
            }
        }.readObject();
    }

这个方法重载了ObjectInputStream中的resolveClass(),新增了一些检查,来确保被读取为反序列化进程部分的任何类,都是不可利用或者处于安全类的白名单中。作为一个替代项,你可以将不熟悉的类加入黑名单——那些会被用来开发的——但这注定失败。因为有太多被称为“小工具”的东西能够高效的列出所有可能被利用的漏洞。

这个简单的检查保护了你的程序,并且不用从底层修改代码。第一步要做的是搜索你的代码,找到所有易受攻击的地方——第二天,所有Contrast的用户就会收到一个更新来完成上面的事情。一旦发现程序包中存在由于反序列化不受信任数据而暴露的地方,你就会收到通知。

本文已被发布在程序员资料库

并被推荐到极客头条

转载请注明出处和原文出处

需要译稿请联系QQ:545870054
或者邮件:fan_xq@live.com

发表评论

电子邮件地址不会被公开。 必填项已用*标注