删一 发表于 2025-6-9 15:49:26

07jdk7u21原生利用链

JDK7u21

反序列化的关键


[*]在于找到可以动态方法执行的代码:例如CC链中的Transformer,CB链中的PropertyUtils#getProperty
JDK7u21中动态方法执行的点,AnnotationInvocationHandler#equalsImpl中的hisValue = memberMethod.invoke(o)。
private Boolean equalsImpl(Object o) {
      if (o == this)
            return true;

      if (!type.isInstance(o))
            return false;
      for (Method memberMethod : getMemberMethods()) {
            String member = memberMethod.getName();
            Object ourValue = memberValues.get(member);
            Object hisValue = null;
            AnnotationInvocationHandler hisHandler = asOneOfUs(o);
            if (hisHandler != null) {
                hisValue = hisHandler.memberValues.get(member);
            } else {
                try {
                  hisValue = memberMethod.invoke(o);
                } catch (InvocationTargetException e) {
                  return false;
                } catch (IllegalAccessException e) {
                  throw new AssertionError(e);
                }
            }
            if (!memberValueEquals(ourValue, hisValue))
                return false;
      }
      return true;
    }

private Method[] getMemberMethods() {
      if (memberMethods == null) {
            memberMethods = AccessController.doPrivileged(
                new PrivilegedAction<Method[]>() {
                  public Method[] run() {
                        final Method[] mm = type.getDeclaredMethods();
                        validateAnnotationMethods(mm);
                        AccessibleObject.setAccessible(mm, true);
                        return mm;
                  }
                });
      }
      return memberMethods;
    }AnnotationInvocationHandler#equalsImpl是一个私有方法,仅在AnnotationInvocationHandler#invoke中被调用,它遍历执行了this.type的所有方法,如果这里的this.type为TemplatesImpl,那就可以实现任意代码执行。
public Object invoke(Object proxy, Method method, Object[] args) {
      String member = method.getName();
      Class<?>[] paramTypes = method.getParameterTypes();

      // Handle Object and Annotation methods
      if (member.equals("equals") && paramTypes.length == 1 &&
            paramTypes == Object.class)
            return equalsImpl(args);
      if (paramTypes.length != 0)
            throw new AssertionError("Too many parameters for an annotation method");

      switch(member) {
      case "toString":
            return toStringImpl();
      case "hashCode":
            return hashCodeImpl();
      case "annotationType":
            return type;
      }

      // Handle annotation member accessors
      Object result = memberValues.get(member);

      if (result == null)
            throw new IncompleteAnnotationException(type, member);

      if (result instanceof ExceptionProxy)
            throw ((ExceptionProxy) result).generateException();

      if (result.getClass().isArray() && Array.getLength(result) != 0)
            result = cloneArray(result);

      return result;
    }前面找到动态代码执行的关键后,构造链条的关键即在于如何调用equalsImpl和equalsImpl如何进行任意代码执行。
如何调用equalsImpl

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

equals方法通常用于比较两个对象是否是同一引用,一个常见场景是集合set,集合是不允许重复对象的,所以在添加对象时势必涉及到比较操作。
// 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
页: [1]
查看完整版本: 07jdk7u21原生利用链