Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
WebLogic-Shiro-shell — WebLogic의 CVE-2020-2883을 악용해 Shiro rememberMe 역직렬화 취약점을 공격하고, 원클릭으로 AntSword filter 메모리 셸을 등록합니다. | Kitploit
도구/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 역직렬화 취약점을 공격하고, 원클릭으로 AntSword filter 메모리 셸을 등록합니다.

저장소 보기
53160126년 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Java 역직렬화 기술 공유

이번 공유에서 다루는 내용은 다음과 같습니다:

  1. Java 직렬화 및 역직렬화 기초
  2. 역직렬화 시 왜 취약점이 발생하는가?
  3. Java 리플렉션
  4. ysoserial CommonsCollections2, CommonsCollections5
  5. Java ClassLoader가 클래스를 로드하는 여러 방법
  6. WebLogic CVE-2020-2555 CVE-2020-2883 RCE
  7. Shiro-550 rememberMe 하드코딩으로 인한 역직렬화 RCE
  8. WebLogic + Shiro 역직렬화 원클릭 filter 메모리 셸 등록

Java 직렬화 및 역직렬화 기초

Java 직렬화란 Java 객체를 바이트 시퀀스로 변환하는 과정을 말하며, 메모리, 파일, 데이터베이스에 저장하기 쉽도록 하기 위함입니다. ObjectOutputStream 클래스의 writeObject() 메서드가 직렬화를 구현하여 Java 객체를 바이트 시퀀스로 변환합니다.

Java 역직렬화란 바이트 시퀀스를 Java 객체로 복원하는 과정을 말하며, ObjectInputStream 클래스의 readObject() 메서드가 역직렬화에 사용됩니다.

간단한 예를 들어보겠습니다. 코드 SerializeAndDeserialize를 참조하세요. ps: 여기서 코드 내 강제 형변환에 주목하세요```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, 배열, Object 객체 등 Java 내장 데이터 타입은 모두 직렬화를 구현할 수 있으며, 우리가 직접 작성한 Person, Dog 클래스도 Serializable 인터페이스만 구현하면 직렬화와 역직렬화를 할 수 있습니다.



## 왜 역직렬화할 때 취약점이 발생할까요?

코드 한 부분을 살펴보겠습니다. 지금 악의적인 엔티티 클래스 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});
    }
}

그 readObject에는 명령을 실행하는 코드 Runtime.getRuntime().exec(new String[]{"cmd", "/c", name})가 존재하며, name 매개변수는 실행할 명령이다. 그렇다면 악성 객체를 구성하여 name 속성을 실행할 명령으로 할당하면, 역직렬화 시 readObject가 트리거되면서 RCE가 발생한다. 다음과 같다.```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)

이제 우리는 역직렬화가 어떻게 RCE로 이어지는지 알게 되었습니다. 하지만 개발 중에 이렇게 직접 작성할 수도 없으므로, 여기서 이용 체인(gadget chain)을 찾는 것이 중요해집니다. 역직렬화 취약점에는 세 가지가 필요합니다.

1. 역직렬화 진입점(source)
2. 목표 메서드(sink)
3. 이용 체인(gadget chain)

위 그림의 출력 결과를 자세히 보면 readObject 메서드뿐만 아니라 toString(), 무인자 생성자, set, get 메서드도 함께 호출된 것을 확인할 수 있습니다. 따라서 실제로 이용 체인을 찾을 때는 readObject() 메서드만 주목해서는 안 됩니다.

그리고 이제 **리플렉션**에 대해 이해할 필요가 있습니다. 앞서 **강제 형변환** 문제를 언급했는데, 실제 개발에서 readObject 내부에서 로직 처리가 이루어질 때 전달된 객체의 구체적인 데이터 타입을 알 수 없는 경우 리플렉션을 통해 호출을 판단합니다. 그리고 리플렉션은 우리가 RCE에 도달하는 중요한 수단입니다.

## Java 리플렉션

리플렉션이란 무엇일까요? '리플렉션'에는 '반(反)' 자가 있습니다. 그렇다면 리플렉션을 설명하려면 '정방향 호출(正射)'부터 시작해야 합니다. 코드를 보겠습니다. 이것은 제 엔티티 클래스입니다.```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;
    }
}

일반 작성법```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方法 } }

간단히 말해 `new`를 통해 ReflectionClass 인스턴스를 생성한 다음, 인스턴스를 통해 그에 속한 메서드를 호출하는 것이 바로 "직접 호출"입니다. 하지만 `new`를 할 때 클래스 이름을 모르면 어떻게 해야 할까요? private로 보호된 메서드는 어떻게 호출할까요? 이때 리플렉션의 역할이 드러납니다. 아래 코드를 보세요.```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();

        // setName("jack")
        Method setName = aClass.getDeclaredMethod("setName",String.class);
        setName.invoke(o, "jack");

        // say()
        Method say = aClass.getDeclaredMethod("say",null);
        Object o1 = say.invoke(o, null);
        System.out.println(o1);

        // evil("calc")
        // 反射可以修改方法的修饰符来调用private方法
        Method evil = aClass.getDeclaredMethod("evil", String.class);
        evil.setAccessible(true);
        evil.invoke(o,"calc");
    }
}

클래스 이름을 미리 알 필요 없이, org.chabug.entity.ReflectionClass 클래스를 약간 수정해서 매개변수로 전달하면 되며, setAccessible을 통해 private으로 보호된 메서드나 필드를 가져올 수 있다.

이제 취약점에서 출발하여 리플렉션이 역직렬화에서 수행하는 역할과 역직렬화 호출 체인(가젯 체인) 발굴에 대해 자세히 알아보자.

ysoserial CommonsCollections2、CommonsCollections5

ysoserial은 Java 역직렬화 익스플로잇을 생성하는 도구로, 이미 알려진 여러 익스플로잇을 포함하고 있다. 예를 들어 CommonsCollections의 몇 가지 이용 체인(exploitation chain)이 있다. 이번에 분석할 것은 CC2, CC5 두 체인이다. 이 두 체인을 분석하는 이유는 CC2에는 바이트코드를 정의하는 조작이 사용되고, CC5에서는 리플렉션과 체인 호출에 대한 이해를 심화하기 위해서다.

먼저 더 이해하기 쉬운 CC5 체인을 살펴보자.

CommonsCollections5

도구 다운로드