Java 역직렬화의 CommonsCollections(CC1) 기본 사항


머리말

      이 문서에는 Java CC1(Deserialization CommonsCollections)에 대한 몇 가지 기본 지식 개념이 포함되어 있습니다.


1. 기본 소개 및 환경

    1.Apache Commons 컬렉션 소개

      Apache Commons Collections는 Java 애플리케이션 개발에서 매우 일반적으로 사용되는 도구 라이브러리로, 많은 강력한 데이터 구조를 추가하고 Java 애플리케이션 개발을 단순화하며 Java에서 컬렉션 데이터를 처리하는 데 인정받는 표준이 되었습니다. Weblogic, WebSphere, Jboss, Jenkins 등 많은 일반 응용 프로그램은 모두 Apache Commons Collections 도구 라이브러리를 사용하고 있으며, 도구 라이브러리에서 역직렬화 취약점이 발생하면 해당 응용 프로그램도 영향을 받기 때문에 역직렬화 취약점이 매우 심각합니다. 이유.

    2. 취약성의 원리

      Apache Commons Collections는 Transformer 클래스를 제공하며, 이 인터페이스의 기능은 한 개체를 다른 개체로 변환하는 것입니다.
      그러면 전체 활용 체인이 이 클래스에 집중해야 합니다.

  • InvokeTransformer: 리플렉션을 통해 개체를 반환합니다.
  • ChainedTransformer: 변환기를 체인에 연결하고 체인의 각 변환기를 통해 개체를 차례로 변환합니다.
  • ConstantTransformer: 객체를 상수로 변환하고 반환합니다.

    3. 이 기사의 환경 버전

      IDEA 버전은 2021.1.3입니다.
      Jdk 버전은 8u65입니다. CC1 익스플로잇 체인이 8u71 버전에서 수정되었기 때문입니다. 다운로드 주소: https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html
      Maven 버전: 3.6.3, 다운로드 링크: https://archive.apache.org/dist/maven / maven-3/3.6.3/binaries/
      이 문서의 CommonsCollections 버전은 3.2.1이며 3.1~3.21 사이일 수 있습니다.

<dependencies>
    <!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>
</dependencies>

      디버깅을 용이하게 하기 위해서는 자바 소스 코드를 추가해야 하며, 다운로드 주소는 https://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/af660750b2f4입니다.

    4. 구축 과정

     1) 해당 버전의 openjdk 소스 코드를 다운로드합니다. 그리고 폴더에 압축을 풀어주세요.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
     2) jdk1.8.0_65 폴더에 src.zip의 압축을 푼다. 그런 다음 다운로드한 openjdk에 있는 jdk-af660750b2f4\src\share\classes의 sun 폴더를 압축이 풀린 src 폴더에 복사합니다.
여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
     3) IDEA는 Maven 프로젝트를 생성하고 Project SDK는 다운로드한 jdk8u65의 경로를 선택합니다. 그런 다음 프로젝트 이름을 쓰고 다음 단계에서 저장 경로를 만듭니다.
여기에 이미지 설명을 삽입하세요.
     4) 생성 후 ProjectStructure 프로젝트 구조를 선택합니다.
여기에 이미지 설명을 삽입하세요.
     5) SDK를 선택하고 Sourcepath를 클릭한 후 src를 추가하고 마지막으로 적용하고 저장합니다.
여기에 이미지 설명을 삽입하세요.
     6) 그런 다음 pom.xml 파일에 commons collections 3.2.1 버전을 추가하고 리소스를 직접 다운로드하거나 마우스 오른쪽 버튼을 클릭하여 프로젝트를 다시 로드하여 리소스를 다운로드합니다.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

2. 기본 학습

   1. 명령 실행 방법

     1) JAVA에서의 일반적인 명령 실행.

public class CC1 {
    
    
    public static void main(String[] atgs) throws Exception
    {
    
    
        // 1.先弹个计算器
        Runtime.getRuntime().exec("calc");
    }
}

여기에 이미지 설명을 삽입하세요.
     2) 공통 반사를 사용하여 명령을 실행합니다.

import java.lang.reflect.Method;

public class CC1 {
    
    
    public static void main(String[] atgs) throws Exception
    {
    
    
//        // 1.先弹个计算器
//        Runtime.getRuntime().exec("calc");


        // 2.写一个普通的反射
        Runtime r = Runtime.getRuntime();
        // 获取Runtime的class
        Class c = Runtime.class;
        // 获取Runtime的exec方法
        Method execMethod = c.getMethod("exec",String.class);
        // 调用exec方法
        execMethod.invoke(r,"calc");
    }
}

여기에 이미지 설명을 삽입하세요.

   2. CC1 체인에 관련된 클래스 소개

     1) Transformer 클래스는 Commons Collections의 맞춤형 기능 클래스 세트입니다. Transformer 클래스의 기능은 객체를 받은 다음 변환 메서드를 호출하여 객체에 대한 일부 작업을 수행하는 것입니다.

public interface Transformer {
    
    
    public Object transform(Object input);
}

     2) InvokerTransformer 역시 Transformer 인터페이스를 구현하는 클래스로, 어떤 메소드든 실행할 수 있습니다. InvokerTransformer 객체를 생성할 때 세 가지 매개변수를 전달해야 합니다. 첫 번째는 실행하려는 메소드의 이름이고, 두 번째는 이 메소드에 필요한 매개변수의 매개변수 유형이고, 세 번째는 이 메소드의 특정 매개변수입니다. InvokerTransformer 클래스에서 변환 메소드를 사용하면 우리가 실행하고 싶은 메소드가 실행되는데, 구체적으로 어떤 객체인지? 이는 변환 메소드의 매개변수를 통해 전달됩니다. 다음으로 코드를 살펴보겠습니다. 첫 번째는 생성 메소드입니다.

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
    
    
    super();
    iMethodName = methodName;
    iParamTypes = paramTypes;
    iArgs = args;
}

      이는 단지 세 개의 매개변수를 할당한 것일 뿐입니다. 다음으로 콜백 변환 메서드를 살펴보겠습니다.

public Object transform(Object input) {
    
    
    if (input == null) {
    
    
        return null;
 }
 try {
    
    
     Class cls = input.getClass();
     Method method = cls.getMethod(iMethodName, iParamTypes);
     return method.invoke(input, iArgs);}
    catch (NoSuchMethodException ex) {
    
    
        throw new FunctorException("InvokerTransformer: The method '" +iMethodName + "' on '" + input.getClass() + "' does not exist");} 
    catch (IllegalAccessException ex) {
    
    
        throw new FunctorException("InvokerTransformer: The method '" +iMethodName + "' on '" + input.getClass() + "' cannot be accessed");} 
    catch (InvocationTargetException ex) {
    
    
        throw new FunctorException("InvokerTransformer: The method '" +iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);}
}

      이런 식으로 입력 개체의 iMethodName 메서드를 실행할 수 있습니다. 원리는 실제로 매우 간단합니다. 리플렉션을 사용하여 이 메서드를 먼저 얻은 다음 입력 개체에서 이 메서드를 실행하는 것입니다. 3) TransformedMap 클래스는 다음을 캡슐화합니다. Decor 메소드
     . Java에서 표준 데이터 구조 Map을 수정하는 데 사용됩니다. 수정된 Map에 새 요소가 추가되면 콜백 함수를 실행합니다. 이 콜백은 전통적인 의미의 콜백 함수는 아니지만 다음과 동일합니다. 객체에서 변환 메소드를 실행하려면 객체의 클래스가 Transformer 인터페이스를 구현해야 합니다. 아래 코드를 보면 keyTransformer는 새로운 요소의 Key를 처리하는 콜백이고, valueTransformer는 새로운 요소의 값을 처리하는 콜백임을 알 수 있는데, externalMap에 새로운 요소를 추가하면 변환 메소드를 호출하게 된다. keyTransformer 또는 valueTransformer에서.

Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, keyTransformer, valueTransformer);

     4) ConstantTransformer 역시 Transformer 인터페이스를 구현한 클래스입니다. 이 클래스는 매우 간단합니다. 매개변수를 갖는 생성자가 있고, 매개변수 유형이 객체입니다. 객체를 전달하면 변환 메소드에서 사용됩니다. 이 개체가 반환됩니다. 이는 변환 메소드에서 전달된 객체 ConstantToReturn을 반환하는 것입니다.

public ConstantTransformer(Object constantToReturn) {
    
    
    super();
    iConstant = constantToReturn;
}
public Object transform(Object input) {
    
    
    return iConstant;
}

     5) 앞서 언급한 것처럼 ConstantTransformer와 InvokerTransformer 두 가지 클래스가 있는데, 하나는 클래스의 객체를 반환하고, 다른 하나는 객체에 있는 메소드를 실행할 수 있는데 그럼 Runtime 클래스에서 exec 메소드를 실행해 볼까요? 분명히 ConstantTransformer 클래스에서 반환된 개체를 InvokerTransformer 클래스의 변환 메서드에 입력하기 위한 매개 변수로 사용할 수 있도록 이 두 가지를 함께 연결하는 클래스도 필요합니다. ChainedTransformer 클래스 ChainedTransformer 클래스는 Transformer 인터페이스를 구현하는 클래스이기도 합니다. 이는 Transformer 인터페이스를 구현하는 여러 내부 클래스를 함께 연결하고 이전 콜백 함수 변환에서 반환된 결과를 다음 콜백 함수 변환의 매개변수로 사용합니다. 전달하면 코드는 다음과 같습니다. 변환을 지속적으로 조정하는 매우 간단한 논리입니다.

public ChainedTransformer(Transformer[] transformers) {
    
    
    super();
    iTransformers = transformers;
}
public Object transform(Object object) {
    
    
    for (int i = 0; i < iTransformers.length; i++) {
    
    
        object = iTransformers[i].transform(object);
        }
    return object;
}

여기에 이미지 설명을 삽입하세요.

추천

출처blog.csdn.net/qq_44029310/article/details/127624206