分类

反序列化漏洞,就是在将一段特定格式的数据流反序列化为特定数据结构或对象时,由于处理不当,而造成的安全漏洞。

特定格式的数据流?那都有哪些格式呢?按照不同的数据流类型,将Java反序列化漏洞分为以下四类:

二进制流反序列化漏洞

1、漏洞产生的必要条件:

(1)使用ObjectInputStream类的readObject()方法反序列化用户可控的数据。

(2)应用系统存在可利用的POP链。

2、漏洞频繁出没的地方:

(1)Weblogic Server

(2)Jboss Server

(3)Java RMI Registry

(4)Apache Shiro

PS:一般自研业务系统很少有反序列化用户输入数据的需求,因此在业务代码中很少出现此类漏洞。

3、漏洞的修复方案

(1)重写ObjectInputStream类的resolveClass方法,在该方法中可设置允许反序列化类的白名单,也可以设置不允许反序列化类的黑名单。

(2)JEP 290安全机制

JDK9中引入了JEP 290机制,开发人员可通过使用反序列化过滤器来预防反序列化漏洞,并且该机制也反向移植到了老版本的JDK(JDK 8u121、JDK 7u131和JDK 6u141)中。

XML数据反序列化漏洞

2.1 XMLDecoder反序列化漏洞

官网介绍如下:

XMLDecoder与ObjectInputStream使用方法类似,前者是对XML数据进行反序列化,后者对字节流进行反序列化。

1、漏洞产生的必要条件

(1)使用XMLDecoder类的readObject()方法反序列化用户可控的数据。

PS:XMLDecoder反序列化漏洞是所有反序列化漏洞中最简单的一个,也是杀伤力最大的一个,因为他可以调用任意类的任意方法,不需要构造POP链。

2、漏洞频繁出没的地方

1、Weblogic Server(wls-async模块)

包含CVE-2017-3506 、CVE-2017-10271、CVE-2019-2725、CVE-2019-2729

3、漏洞的修复方案

对要进行反序列化的XML数据进行严格过滤。

如下为Weblogic修复XMLDecoder反序列化漏洞的代码片段:

try {  SAXParser parser = factory.newSAXParser();  parser.parse(is, new DefaultHandler() {      private int overallarraylength = 0;        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {      if (qName.equalsIgnoreCase("object")) {          throw new IllegalStateException("Invalid element qName:object");      } else if (qName.equalsIgnoreCase("class")) {          throw new IllegalStateException("Invalid element qName:class");      } else if (qName.equalsIgnoreCase("new")) {          throw new IllegalStateException("Invalid element qName:new");      } else if (qName.equalsIgnoreCase("method")) {          throw new IllegalStateException("Invalid element qName:method");      } else {          if (qName.equalsIgnoreCase("void")) {              for(int i = 0; i < attributes.getLength(); ++i) {                  if (!"index".equalsIgnoreCase(attributes.getQName(i))) {                      throw new IllegalStateException("Invalid attribute for element void:" + attributes.getQName(i));                  }              }          }          if (qName.equalsIgnoreCase("array")) {              String attClass = attributes.getValue("class");              if (attClass != null && !attClass.equalsIgnoreCase("byte")) {                  throw new IllegalStateException("The value of class attribute is not valid for array element.");              }          }      }    }  }}      


2.2 XStream反序列化漏洞

官网介绍如下:

一个用于把Java对象序列化为XML数据、把XML数据反序列化为Java对象的类库。

1、漏洞产生的必要条件

(1)使用XStream类的fromXML()方法反序列化用户可控的数据。

(2)当前XStream版本存在可以用的POP链

2、漏洞频繁出没的地方

(1)Apache Struts (S2-052)

(2)eureka-client组件

(3)自研业务系统

3、漏洞的修复方案

(1)通过XStream的addPermission方法来实现白名单控制:

// 首先清除默认设置,然后进行自定义设置xstream.addPermission(NoTypePermission.NONE);// 添加一些基础的类型,如Array、NULL、Primitivexstream.addPermission(ArrayTypePermission.ARRAYS);xstream.addPermission(NullPermission.NULL);xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);// 添加自定义的类列表stream.addPermission(new ExplicitTypePermission(new Class[]{Date.class}));// 添加同一个package下的多个类型xstream.allowTypesByWildcard(new String[] {Blog.class.getPackage().getName()+".*"});

(2)通过XStream的denyPermission方法来实现黑名单控制

PS:不推荐使用,可能被绕过。

(3)使用最新版XStream

Json数据反序列化漏洞

相信各位道友对Fastjson反序列化漏洞都有所了解,这种漏洞是最常出现在业务系统中的。

PS:由于Fastjson在反序列化时,会调用JavaBean对象的setter方法和特定的getter方法,因此我们在做代码审计时,即使应用系统使用了最新版的Fastjson,我们依然要注意一下业务系统自定义的JavaBean对象中的setter、getter方法中是否有些高危操作,防止被攻击。

Yaml数据反序列化漏洞

Yaml数据的反序列化漏洞也相对简单些,其原理类似Fastjson反序列化漏洞,这里以常见的SnakeYaml为例,进行介绍。

1、漏洞产生的必要条件

(1)使用Yaml类的load()或loadAs()等方法反序列化用户可控的数据。

2、漏洞频繁出没的地方

(1)自研业务系统

PS:同样,yaml数据的反序列化漏洞也经常出现在自研业务系统中。

3、漏洞的修复方案

(1)升级SnakeYaml组件版本到2.0及以上版本。

2.0及以上版本中,默认情况下,通过白名单的方式,限制了仅允许反序列化如下标准tag:

对其他自定义的tag,对于最常用的如下ScriptEngineManager攻击向量:

tag:yaml.org,2002:javax.script.ScriptEngineManager

将会抛出异常:

(2)无法升级版本时,也可通过如下构造Yaml对象的方案解决:

Yaml yaml = new Yaml(new SafeConstructor());

该方法同样通过白名单的方式,限制了可反序列化的数据类型:

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本平台和发布者不为此承担任何责任。