跳转至

Hessian 反序列化

流程分析

序列化 会先寻找 Serializer。

if (! Serializable.class.isAssignableFrom(cl)  
&& ! _isAllowNonSerializable) {  
    throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable");  
}

这里可以发现能够序列化非 Serializable 的子类

if (_isEnableUnsafeSerializer  
    && JavaSerializer.getWriteReplace(cl) == null) {  
    return UnsafeSerializer.create(cl);  
}  
else  
    return JavaSerializer.create(cl);

然后判断类中有没有 writeReplace 方法,如果有,那么便使用 JavaSerializer,否则使用 UnsafeSerializer。

一般是用 UnsafeSerializer Wrap。 跳过了 transient 和 static 修饰的字段

if (Modifier.isTransient(field.getModifiers())  
|| Modifier.isStatic(field.getModifiers())) {  
    continue;
}

然后再给每个字段分配 Serializer

private static FieldSerializer getFieldSerializer(Field field)
  {
    Class<?> type = field.getType();

    if (boolean.class.equals(type)) {
      return new BooleanFieldSerializer(field);
    }
    ...
    else
      return new ObjectFieldSerializer(field);
  }

触发点

MapDeserializer#readMap 对 Map 类型数据进行反序列化操作是会创建相应的 Map 对象,并将 Key 和 Value 分别反序列化后使用 put 方法写入数据。在没有指定 Map 的具体实现类时,将会默认使用 HashMap ,对于 SortedMap,将会使用 TreeMap。 - HashMap 在 put 键值对时,将会对 key 的 hashcode 进行校验查看是否有重复的 key 出现,这就将会调用 key 的 hasCode 方法 - TreeMap 在 put 时,由于要进行排序,所以要对 key 进行比较操作,将会调用 compare 方法,会调用 key 的 compareTo 方法 除此之外,还有一个能够利用的是 toString。可以在 expection 处理时通过字符串拼接调用 toString 方法。

限制: - kick-off chain 起始方法只能为 hashCode/equals/compareTo 方法; - 利用链中调用的成员变量不能为 transient 修饰; - 所有的调用不依赖类中 readObject 的逻辑,也不依赖 getter/setter 的逻辑。

参考

  • https://su18.org/post/hessian/

最后更新: June 24, 2023 16:07:08
创建日期: June 24, 2023 16:07:08

评论