找回密码
 立即注册
首页 业界区 科技 07jdk7u21原生利用链

07jdk7u21原生利用链

删一 2025-6-9 15:49:26
JDK7u21

反序列化的关键


  • 在于找到可以动态方法执行的代码:例如CC链中的Transformer,CB链中的PropertyUtils#getProperty
JDK7u21中动态方法执行的点,AnnotationInvocationHandler#equalsImpl中的hisValue = memberMethod.invoke(o)。
  1. private Boolean equalsImpl(Object o) {
  2.         if (o == this)
  3.             return true;
  4.         if (!type.isInstance(o))
  5.             return false;
  6.         for (Method memberMethod : getMemberMethods()) {
  7.             String member = memberMethod.getName();
  8.             Object ourValue = memberValues.get(member);
  9.             Object hisValue = null;
  10.             AnnotationInvocationHandler hisHandler = asOneOfUs(o);
  11.             if (hisHandler != null) {
  12.                 hisValue = hisHandler.memberValues.get(member);
  13.             } else {
  14.                 try {
  15.                     hisValue = memberMethod.invoke(o);
  16.                 } catch (InvocationTargetException e) {
  17.                     return false;
  18.                 } catch (IllegalAccessException e) {
  19.                     throw new AssertionError(e);
  20.                 }
  21.             }
  22.             if (!memberValueEquals(ourValue, hisValue))
  23.                 return false;
  24.         }
  25.         return true;
  26.     }
  27. private Method[] getMemberMethods() {
  28.         if (memberMethods == null) {
  29.             memberMethods = AccessController.doPrivileged(
  30.                 new PrivilegedAction<Method[]>() {
  31.                     public Method[] run() {
  32.                         final Method[] mm = type.getDeclaredMethods();
  33.                         validateAnnotationMethods(mm);
  34.                         AccessibleObject.setAccessible(mm, true);
  35.                         return mm;
  36.                     }
  37.                 });
  38.         }
  39.         return memberMethods;
  40.     }
复制代码
AnnotationInvocationHandler#equalsImpl是一个私有方法,仅在AnnotationInvocationHandler#invoke中被调用,它遍历执行了this.type的所有方法,如果这里的this.type为TemplatesImpl,那就可以实现任意代码执行。
  1. public Object invoke(Object proxy, Method method, Object[] args) {
  2.         String member = method.getName();
  3.         Class<?>[] paramTypes = method.getParameterTypes();
  4.         // Handle Object and Annotation methods
  5.         if (member.equals("equals") && paramTypes.length == 1 &&
  6.             paramTypes[0] == Object.class)
  7.             return equalsImpl(args[0]);
  8.         if (paramTypes.length != 0)
  9.             throw new AssertionError("Too many parameters for an annotation method");
  10.         switch(member) {
  11.         case "toString":
  12.             return toStringImpl();
  13.         case "hashCode":
  14.             return hashCodeImpl();
  15.         case "annotationType":
  16.             return type;
  17.         }
  18.         // Handle annotation member accessors
  19.         Object result = memberValues.get(member);
  20.         if (result == null)
  21.             throw new IncompleteAnnotationException(type, member);
  22.         if (result instanceof ExceptionProxy)
  23.             throw ((ExceptionProxy) result).generateException();
  24.         if (result.getClass().isArray() && Array.getLength(result) != 0)
  25.             result = cloneArray(result);
  26.         return result;
  27.     }
复制代码
前面找到动态代码执行的关键后,构造链条的关键即在于如何调用equalsImpl和equalsImpl如何进行任意代码执行。
如何调用equalsImpl

由于AnnotationInvocationHandler实现了接口InvocationHandler,这里很明显可以采用CC1中用到的动态代理调用AnnotationInvocationHandler#invoke,但是注意到invoke的代码逻辑,我们代理的对象,必须是调用名为equals且只有一个Object类型的参数时,才会触发equalsImpl。
找到equals调用链

equals方法通常用于比较两个对象是否是同一引用,一个常见场景是集合set,集合是不允许重复对象的,所以在添加对象时势必涉及到比较操作。
[code]// HashSet#readObjectprivate void readObject(java.io.ObjectInputStream s)        throws java.io.IOException, ClassNotFoundException {        // Read in any hidden serialization magic        s.defaultReadObject();        // Read capacity and verify non-negative.        int capacity = s.readInt();        if (capacity < 0) {            throw new InvalidObjectException("Illegal capacity: " +                                             capacity);        }        // Read load factor and verify positive and non NaN.        float loadFactor = s.readFloat();        if (loadFactor
您需要登录后才可以回帖 登录 | 立即注册