Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
WebLogic-Shiro-shell — WebLogic利用CVE-2020-2883打Shiro rememberMe反序列化漏洞,一键注册蚁剑filter内存shell | Kitploit
Tools/GitHubGitHub/y4er/weblogic-shiro-shell
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationPayload DevelopmentBinary Exploitation
GitHuby4er/weblogic-shiro-shell

WebLogic-Shiro-shell

WebLogic利用CVE-2020-2883打Shiro rememberMe反序列化漏洞,一键注册蚁剑filter内存shell

View Repository
53160116 years agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Java Deserialization Technology Sharing

This sharing covers the following points:

  1. Java Serialization and Deserialization Basics
  2. Why do vulnerabilities occur during deserialization?
  3. Java Reflection
  4. ysoserial CommonsCollections2, CommonsCollections5
  5. Java ClassLoader: Several methods for loading classes
  6. WebLogic CVE-2020-2555 CVE-2020-2883 RCE
  7. Shiro-550 rememberMe hardcoded key leading to deserialization RCE
  8. WebLogic + Shiro deserialization one-click registration of filter memory shell

Java Serialization and Deserialization Basics

Java serialization refers to the process of converting Java objects into byte sequences for easy storage in memory, files, or databases. The writeObject() method of the ObjectOutputStream class can perform serialization, converting Java objects into byte sequences.

Java deserialization refers to the process of restoring byte sequences back to Java objects. The readObject() method of the ObjectInputStream class is used for deserialization.

Let's take a simple example, see the code SerializeAndDeserialize ps: here focus on the forced type casting in the code```java package org.chabug.demo;

import org.chabug.entity.Dog; import org.chabug.entity.Person; import org.chabug.util.Serializables;

/* 这个例子是为了证明只要实现了Serializable接口的类都可以被序列化 并且Java内置的几大数据类型也可被序列化,因为他们都继承了Object类 */

public class SerializeAndDeserialize {

public static void main(String[] args) throws Exception {
    byte[] bytes;
    String s1 = "I'm a String Object....";
    bytes = Serializables.serializeToBytes(s1);
    Object o1 = Serializables.deserializeFromBytes(bytes);
    System.out.println(o1);

    String[] s2 = new String[]{"tom", "bob", "jack"};
    bytes = Serializables.serializeToBytes(s2);
    String[] o2 = (String[])Serializables.deserializeFromBytes(bytes);
    System.out.println(o2);

    int i = 123;
    bytes = Serializables.serializeToBytes(i);
    int o3 = (Integer) Serializables.deserializeFromBytes(bytes);
    System.out.println(o3);

    // 一只名叫woody的狗
    Dog dog = new Dog();
    dog.setName("woody");

    // tom
    Person tom = new Person();
    tom.setAge(14);
    tom.setName("tom");
    tom.setSex("男");
    tom.setDog(dog);

    bytes = Serializables.serializeToBytes(tom);
    Person o = (Person) Serializables.deserializeFromBytes(bytes);
    System.out.println(o);

}

}

String, Integer, array, Object and other built-in data types in Java can all be serialized. Custom classes like Person and Dog that we write ourselves can also be serialized and deserialized as long as they implement the Serializable interface.

## Why does a vulnerability arise during deserialization?

Look at a piece of code. Now there is a malicious entity class EvilClass.```java
package org.chabug.entity;

import java.io.ObjectInputStream;
import java.io.Serializable;

public class EvilClass implements Serializable {
    String name;

    public EvilClass() {
        System.out.println(this.getClass() + "的EvilClass()构造方法被调用!!!!!!");
    }

    public EvilClass(String name) {
        System.out.println(this.getClass() + "的EvilClass(String name)构造方法被调用!!!!!!");
        this.name = name;
    }

    public String getName() {
        System.out.println(this.getClass() + "的getName被调用!!!!!!");
        return name;
    }

    public void setName(String name) {
        System.out.println(this.getClass() + "的setName被调用!!!!!!");
        this.name = name;
    }

    @Override
    public String toString() {
        System.out.println(this.getClass() + "的toString()被调用!!!!!!");
        return "EvilClass{" +
                "name='" + getName() + '\'' +
                '}';
    }

    private void readObject(ObjectInputStream in) throws Exception {
        //执行默认的readObject()方法
        in.defaultReadObject();
        System.out.println(this.getClass() + "readObject()被调用!!!!!!");
        Runtime.getRuntime().exec(new String[]{"cmd", "/c", name});
    }
}

There is code that executes commands in its readObject: Runtime.getRuntime().exec(new String[]{"cmd", "/c", name}), where the name parameter is the command to be executed. Therefore, we can construct a malicious object, set its name attribute to the command to be executed, and when deserialization triggers readObject, RCE will occur. As follows:```java package org.chabug.demo;

import org.chabug.entity.EvilClass; import org.chabug.util.Serializables;

public class EvilSerialize { public static void main(String[] args) throws Exception { EvilClass evilObj = new EvilClass(); evilObj.setName("calc"); byte[] bytes = Serializables.serializeToBytes(evilObj); EvilClass o = (EvilClass) Serializables.deserializeFromBytes(bytes); System.out.println(o); } }

![image-20200822105256120](https://assets.kitploit.com/production/public/readmes/21799/7f07c0c8196e56e1d554bce64f73f069bdd3e589a3302936c831903e5f7e5539.png)

So now we know how deserialization can achieve RCE, but in actual development, code wouldn't be written this directly, so it comes down to finding the gadget chain. A deserialization vulnerability requires three things:

1. Deserialization entry point (source)
2. Target method (sink)
3. Gadget chain

Looking closely at the output in the image above, it not only triggered the `readObject` method, but also triggered `toString()`, the no-arg constructor, `set`, and `get` methods. So in practice, when searching for gadget chains, we need to pay attention to more than just the `readObject()` method.

Now we need to understand **reflection**. Earlier we mentioned the issue of **forced type casting**. In actual development, logic is processed in `readObject`. When the specific data type of the incoming object is unknown, reflection is used to determine and invoke methods. Reflection is a crucial means to achieve RCE.

## Java Reflection

What is reflection? The term "reflection" contains the idea of "turning back." To explain reflection, we should start with "direct" invocation. Look at the code. Here is my entity class.```java
package org.chabug.entity;

import java.io.IOException;

public class ReflectionClass {
    String name;

    public ReflectionClass(String name) {
        this.name = name;
    }

    public ReflectionClass() {
    }

    public String say() {
        return this.name;
    }

    private void evil(String cmd) {
        try {
            Runtime.getRuntime().exec(new String[]{"cmd","/c",cmd});
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return "ReflectionClass{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

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

Normal usage```java package org.chabug.demo;

import org.chabug.entity.ReflectionClass;

public class ReflectionDemo { public static void main(String[] args) { ReflectionClass demo = new ReflectionClass(); demo.setName("hello"); System.out.println(demo.say()); // demo.evil("calc"); // 不能够调用private方法 } }

It's very simple: create a ReflectionClass instance via new, then call its methods through the instance. This is "forward mapping". But what if you don't know the class name when using new? How do you call protected/private methods? This is where the role of reflection becomes apparent. Look at the following code```java
package org.chabug.demo;

import org.chabug.entity.ReflectionClass;

import java.lang.reflect.Method;

public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // new
        Class<?> aClass = Class.forName("org.chabug.entity.ReflectionClass");
        Object o = aClass.newInstance();
Download Tool