反序列化漏洞屡被黑客利用,危害巨大,代码怎样写才安全?

反序列化漏洞出现很久了,一直到现在都很流行,以致OWASP组织将“不安全的反序列化”列为2017年10项最严重的Web 应用程序安全风险榜的第8位。

就在2017年12月22日和24日,国家信息安全漏洞共享平台(CNVD)连续发布了《关于WebLogic Server WLS 组件存在远程命令执行漏洞的安全公告》第一版和第二版。漏洞编号为CNVD-2017-31499,对应CVE-2017-10271。

同时,在12月22日,各大安全网站都有报道称,黑客利用WebLogic 反序列化漏洞(CVE-2017-3248)和WebLogic WLS 组件漏洞(CVE-2017-10271)对企业服务器发起大范围远程攻击,有大量企业的服务器被攻陷。这两个漏洞都是反序列化漏洞,可见其危害之大。

因为网上已有大量的文章对这些漏洞进行了分析,并提供了修复方案,因此,我不再重复。

我这里关注的是,作为程序员,对反序列化代码要怎样写才安全?

序列化就是把对象转换成一种数据格式,如Json、XML等文本格式或二进制字节流格式,便于保存在内存、文件、数据库中或者在网络通信中进行传输。反序列化是序列化的逆过程,即由保存的文本格式或字节流格式还原成对象。

很多编程语言都提供了这一功能,但不幸的是,如果应用代码允许接受不可信的序列化数据,在进行反序列化操作时,可能会产生反序列化漏洞,黑客可以利用它进行拒绝服务攻击、访问控制攻击和远程命令执行攻击。

Java语言中实现安全地反序列化对象

Java中,ObjectOutputStream类的writeObject()方法实现序列化;ObjectInputStream类的readObject()方法用于反序列化。

(1)重载ObjectInputStream的resolveClass() 方法,只对允许的类进行反序列化操作。

代码示例如下:

public class LookAheadObjectInputStream extends ObjectInputStream /*** 只反序列化Bicycle类*/@Overrideprotected Class resolveClass(ObjectStreamClass desc) throws IOException,ClassNotFoundException return super.resolveClass(desc);}}

可以使用第三方提供的库,它们支持对className进行白名单、黑名单校验,如SerialKiller。

将你应用程序中类似下面的代码:

ObjectInputStream ois = new ObjectInputStream(is);String msg = (String) ois.readObject();

替换成类似下面的代码,即用SerialKiller类替换ObjectInputStream类:

ObjectInputStream ois = new SerialKiller(is, "/etc/serialkiller.conf");String msg = (String) ois.readObject();

serialkiller.conf文件中保存相关的配置信息,如黑名单、白名单等,示例如下:

6000

false true/tmp/serialkiller.log bsh.XThis$bsh.Interpreter$ com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase$ org.mozilla.javascript..*$[...]

org.apache.commons.collections.functors.InstantiateTransformerorg.apache.commons.collections.functors.ConstantTransformerorg.apache.commons.collections.functors.ChainedTransformerorg.apache.commons.collections.functors.InvokerTransformer[...].*

(2)防止反序列化域对象。

有些应用程序对象可能强制要求实现Serializable,为了保证这些应用程序对象不能被反序列化,可以将readObject()声明为final并且总是抛出异常。

private final void readObject(ObjectInputStream in) throws java.io.IOException

(3)使用Agent代理加固所有java.io.ObjectInputStream的操作

前面提到的方法是通过子类化java.io.ObjectInputStream实现安全的反序列化操作,但是,如果你不拥有相关的代码或者等不及相关的补丁,那么这时使用一个Agent代理是最好的方式。但是,要从全局的角度对ObjectInputStream进行安全加固,只能使用黑名单校验,因为不太可能确定应用程序允许反序列化的所有类的清单来作为白名单,并且,这个黑名单要经常更新。

要启用Agent代理,添加以下JVM参数即可:

-javaagent:name-of-agent.jar

同样,也有一些第三方的库实现这个功能,如contrast-rO0等。

语言无关的安全反序列化方法

(1)使用纯数据格式

避免使用反序列化是减少风险的最好方式。使用纯数据格式如Json、XML,使数据对象和业务对象分离,这样减少了出现反序列化漏洞的机会。当然,在处理纯数据时,也有可能会出现漏洞。

(2)对反序列化数据进行签名

不要反序列化不可信的数据。在序列化时,对相关的数据进行签名,对没有通过验证的数据不进行反序列化。

本文来自企鹅号 - 威客安全媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Albert陈凯

Apache Avro是什么干什么用的(RPC/序列化)

Avro总结(RPC/序列化) Avro(读音类似于[ævrə])是Hadoop的一个子项目, 由Hadoop的创始人Doug Cutting(也是Lucene...

4124
来自专栏架构之路

spark 2.3 导致driver OOM的一个SparkPlanGraphWrapper源码的bug

长话短说,我们部门一个同事找到我,说他的spark 2.3 structured streaming程序频繁报OOM,从来没有坚持过超过三四天的,叫帮看一下。 ...

1282
来自专栏解决发现

CPU占用率100%的解决方法

图:优化前(我的电脑是四核cpu,所以单线程无限无阻塞循环占用率不会达到100%)

5730
来自专栏Golang语言社区

使用Go语言框架进行web开发笔记

前言 关于golang的web开发有不少框架,例如 martini, gin, revel,gorilla等。 之前玩过revel,感觉封装的太多了,作为一个小...

4217
来自专栏Golang语言社区

Golang使用pprof监控性能及GC调优

作者:峰云就她了 链接:http://xiaorui.cc/?p=3000 來源:个人博客

3993
来自专栏Crossin的编程教室

pycharm 如何程序运行后,仍可查看变量值?

来出自知乎同名问题。 因为觉得这个问题挺实用,且确实有很多人不了解,故将自己的回答搬运到这里。 我自己开发时候也经常遇到这样的需求:程序运行后,结果不正确,想要...

5488
来自专栏mini188

聊聊从web session的共享到可扩展缓存设计

先从web session的共享说起 许多系统需要提供7*24小时服务,这类系统肯定需要考虑灾备问题,单台服务器如果宕机可能无法立马恢复使用,这必定影响到服务。...

2176
来自专栏lgp20151222

drools的error:Jboss rule 6.4.0 Cannot find a default StatelessKieSession

drools的kmodule.xml文件,如果是默认加载必须放在META-INF的文件夹下,如下图

1272
来自专栏博客园迁移

日常理解

{ 空 } 1. 什么叫线程安全?servlet是线程安全吗? { 答:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次...

902
来自专栏Java帮帮-微信公众号-技术文章全总结

Java并发编程,一定要有自己的理解【面试+工作】

编写优质的并发代码是一件难度极高的事情。Java语言从第一版本开始内置了对多线程的支持,这一点在当年是非常了不起的,但是当我们对并发编程有了更深刻的认识和更多的...

1597

扫码关注云+社区

领取腾讯云代金券