欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

浅析Java序列化和反序列化

来源:本站整理 作者:佚名 时间:2019-01-15 TAG: 我要投稿
        this.replacementField = s;
    }
    public SerializationReplacementClass() {
        this.replacementField = "replace";
    }
}
public class SerializationDemo implements Serializable {
    // omit
    private Object writeReplace() {
        return new SerializationReplacementClass();
    }
    // omit
    public static void main(String[] args) throws ClassNotFoundException {
        // omit
        SerializationReplacementClass demo = (SerializationReplacementClass) in.readObject();
    }
}
从序列化之后得到的二进制串中可以看到目标对象已经被替换成了SerializationReplacementClass:
ac ed 00 05 73 72 00 1d  53 65 72 69 61 6c 69 7a    ....sr.. Serializ
61 74 69 6f 6e 52 65 70  6c 61 63 65 6d 65 6e 74    ationRep lacement
43 6c 61 73 73 32 71 ac  e9 c1 d3 0b 7b 02 00 01    Class2q. ....{...
4c 00 10 72 65 70 6c 61  63 65 6d 65 6e 74 46 69    L..repla cementFi
65 6c 64 74 00 12 4c 6a  61 76 61 2f 6c 61 6e 67    eldt..Lj ava/lang
2f 53 74 72 69 6e 67 3b  78 70 74 00 07 72 65 70    /String; xpt..rep
6c 61 63 65                                         lace
而在反序列化之后得到的对象的replacementField字段值则为resolve,但在此之前readObject()也会被正常调用,当时replacementField字段值为replace。
关于Externalizable
Serializable接口还有一个比较常见的子类Externalizable,它比它爸爸特殊的地方就在于它需要自己实现读写方法 (readExternal()和writeExternal()) ,同时必须包含一个自己的无参构造方法 (默认隐式的也可以) 。
仍以示例说话:
public class ExternalizationDemo implements Externalizable {
    private String stringField;
    private int intField;
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(this.stringField);
        out.writeInt(this.intField);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException {
        this.stringField = "hello, i'm " + in.readUTF();
        this.intField = in.readInt() + 100000;
    }
    public ExternalizationDemo(String s, int i) {
        this.stringField = s;
        this.intField = i;
    }
    public ExternalizationDemo() {}
}
序列化之后得到的二进制串如下:
ac ed 00 05 73 72 00 13  45 78 74 65 72 6e 61 6c    ....sr.. External
69 7a 61 74 69 6f 6e 44  65 6d 6f d9 a9 04 75 84    izationD emo...u.
5d 06 8f 0c 00 00 78 70  77 0b 00 05 67 79 79 79    ].....xp w...gyyy
79 00 01 7d f1 78                                   y..}.x
与Serializable的区别:
对象的序列化属性标志位为0x0c,包括Serializable和Block Data的标志
序列化类的字段个数固定为0
序列化调用writeExternalData()转给类自定义的写方法,将写入的数据包装在新的Block Data块中,第一个字节为块长度 (不含块头尾标识)
反序列化调用readExternalData()转给类自定义的读方法,再调用对象的无参构造方法 (若不存在,则返回null) 进行实例化
 
反序列化漏洞
通过以上对Java的序列化机制的大致了解,我们可以想象一个场景 (有基础的同学可以跳过本部分内容,当然,看一看也没坏处) :
当服务端允许接收远端数据进行反序列化时,客户端可以提供任意一个服务端存在的对象 (包括依赖包中的对象) 的序列化二进制串,由服务端反序列化成相应对象。如果该对象是由攻击者『精心构造』的恶意对象,而它自定义的readObject()中存在着一些『不安全』的逻辑,那么在对它反序列化时就有可能出现安全问题。
说到这,我提三个问题,请大家跟着我的思路去分析,先来看看第一个:
为什么需要依赖反序列化对象的自定义readObject()?
大家都知道,正常来说,反序列化只是一个对象实例化然后赋值的过程,如果之后不主动调用它的内部方法,理论上最多只能控制它字段的值而已。那么有没有什么办法能够让它执行反序列化以外的逻辑呢?毕竟做的越多中间产生问题的概率就越大。

上一页  [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载