Android安全攻击——对象序列化OOM问题

前言


        最近在项目中使用ObjectInputStream/ObjectOutputStream进行对象的序列化和反序列化,出现了OOM的问题,在解决的过程中简单的研究了一下对象的序列化和反序列化(使用Serializable接口)的过程,简单做一个记录。发现了一个持久化存储序列化数据的安全风险,可能会受到恶意攻击,导致必现的OOM。

使用场景


1 数据使用方案


        持久化过程:应用在使用过程中,首先使用ObjectOutputStream的writeObject接口将对象序列化成byte数据,然后利用加密算法对序列化数据进行加密,最终将加密后的数据持久化存储到应用的数据目录下的某个文件中。



        读取解析过程:首先将数据从文件中读取出来,然后用对应的解密算法解密,最后使用对应的ObjectInputStream的readObject接口将字节流解析成对应的对象。



2 遇到的问题

        上述方案在使用的过程中,遇到以下两种OOM的崩溃

(1) OOM 1
java.lang.OutOfMemoryError: Failed to allocate a 942137073 byte allocation with 4194240 free bytes and 487MB until OOM
	at java.io.ObjectInputStream.readBlockDataLong(ObjectInputStream.java:569)
	at java.io.ObjectInputStream.readContent(ObjectInputStream.java:699)
	at java.io.ObjectInputStream.discardData(ObjectInputStream.java:636)
	at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1662)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:657)
	at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1782)
	at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:761)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)
(2) OOM 2
java.lang.OutOfMemoryError: Failed to allocate a 789137073 byte allocation with 2317152 free bytes and 456MB until OOM  
    at java.io.DataInputStream.decodeUTF  
    at java.io.DataInputStream.decodeUTF  
    at java.io.ObjectInputStream.readContent(ObjectInputStream.java:699)  
    at java.io.ObjectInputStream.discardData(ObjectInputStream.java:636)  
    at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1662)  
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:657)  
    at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1782)  
    at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:761)  
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)  
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)  
        堆栈里面大致的意思是,在用ObjectInputStream的readObject接口进行对象的反序列化的时候,需要分配900M+/700M+的内存,导致上层出现OOM,众所周知,应用java层能够分配的最大内存由系统属性dalvik.vm.heapsize定义,这个值根据不同的厂商和机器都有可能是不一样的,我手上的测试机配如下:


        该机器的heapsize设置为256M,也就是该机器的每个应用虚拟机能够分配的最大内存即为256M,当虚拟机需要的内存超过256M时,会出现OutOfMemoryError的问题,这边顺便记录一下,很多人用Exception去捕获所有的异常,但是这样并不能捕获OutOfMemoryError,看一下继承关系:


        由继承关系可知,OutOfMemoryError是继承自Error,和Exception并不是一个继承分支,因此想要捕获包括Error在内的所有异常,必须使用Throwable去捕获。

3 分析问题


3.1 堆栈分析


        上述两个OOM实际上出现的原因是一样的,下面使用OOM1来着重分析这个问题,也就是最终调用ObjectInputStream.readBlockDataLong出现的OOM问题,先看一下这个函数:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值