在2014年,Jann Horn发现一个安卓的提权漏洞,该漏洞允许恶意应用从普通应用权限提权到system用户执行命令,漏洞信息与POC见(1]。漏洞的成因源于在安卓系统(<5.0)中,java.io.ObjectInputStream并未校验输入的java对象是否是实际可序列化的。攻击者因此可以构建一个不可序列化的java对象实例,恶意构建其成员变量,当该对象实例被ObjectInputStream反序列化时,将发生类型混淆,对象的Field被视为由本地代码处理的指针,使攻击者获得控制权。这就是CVE-2014-7911。在了解它的详细信息之前我们先了解以下基础知识:

Android IPC机制

Android应用之间使用沙盒进行隔离用以保障安全性。不过,它们之间可以通过Intent消息机制进行交互。交互时复杂数据类型的传递必须由发送方进行序列化,然后由接收方反序列化。为了方便开发者,Java为序列化提供了内置支持。

Java序列化

序列化Serializable的作用是将数据对象存入字节流当中,在需要时重新生成对象。Android中Intent中传递对象进行序列化有两种方法,一种是Bundle.putSerializable(Key,Object),另一种是Bundle.putParcelable(Key, Object)。前者是实现了Serializable接口,而后者是实现了Parcelable接口。Serializable使用IO读写存储在硬盘上,而Parcelable是直接在内存中读写,很明显内存的读写速度通常大于IO读写,所以在Android中通常优先选择Parcelable。但是Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable在外界有变化的情况下不能很好的保证数据的持续性。所以在这种情况下会使用Serializable。

implements Serializable接口的的作用就是给对象打了一个标记,系统会自动将其序列化。

例如,序列化(和其它)的对象可以通过以下形式添加到Intent的extras中:

 SerializableTypeobj = …

 Bundle b = intent.getExtras();

 b.putString(“foo”, “some string”);

 b.putSerializable(“bar”, obj);

接收数据的代码如下:

 Bundle b = intent.getExtras();

 String foo = (String)b.getString(“foo”);

 SerializableTypeobj = (SerializableType)b.getSerializable(“bar”);

java垃圾回收机制(GC)

我们主要介绍一下java垃圾回收机制中的finalize()方法。

finalize()方法是所有实体对象都具有的方法,因为这个是Object类定义的,常被误认为是垃圾回收的方法或者叫做析构函数,其实并非如此。finalize在JVM内存回收前会被调用(但并非绝对),而即使不调用它,JVM回收机制通过后面所述的一些算法就可以定位哪些是垃圾内存,那么这个拿来干什么用呢?

finalize()其实是要做一些特殊的内存回收操作,如果对JAVA研究稍微多一点,大家会发现JAVA中有一种JNI的机制,即:Java native interface,这种属于JAVA本地接口调用,即调用本地的其它语言信息,JAVA虚拟机底层调用也是这样实现的,这部分调用中可能存在一些对C、C++语言的操作,在C和C++内部通过new、malloc、realloc等关键词创建的对象垃圾回收机制是无能为力的,因为这不是它要管理的范围,而平时这些对象可能被JAVA对应的实体所调用,那么需要在对应JAVA对象放弃时(并不代表回收,只是程序中不使用它了)去调用对应的C、C++提供的本地接口去释放这段内存信息,它们的释放同样需要通过free或delete去释放,所以我们一般情况下不要滥用finalize(),可能你会联想到另一类某些特殊引用对象的释放,如层数引用太多,JAVA虚拟机有些时候不知道这一线的对象是否都可能被回收,那么,你可以自己将finalize()重写,并将内置对象的句柄先释放掉,这样也是没有问题的,不过一般不要滥用。

了解了这些知识后,我们说下CVE-2014-7911的细节,大概是这样的:system_server是一个拥有system权限的关键系统进程,任意应用可向其发送可序列化对象,虽然system_server并不会主动调用该对象的方法,但是在系统GC该对象时会调用到其finalize方法。Jann Horn发现android.os.BinderProxy这个类在finalize方法里调用了一个native指针,而这个指针可被攻击者控制指向任意地址,因此在GC时有机会造成代码执行。

但android.os.BinderProxy是一个不能被序列化的类,因此理论上我们并不能通过发送它的实例来控制将要攻击的目标进程代码执行,但由于java.io.InputStream没有检查接收到的对象是否可序列化,因此我们可以通过特殊方法构造一个被序列化了的伪android.os.BinderProxy来达到目的。值得注意的是,尽管Android采用了ASLR机制,但为了获得正确的地址,可以基于这样一个事实:system_server和攻击者app都是从同一个进程-Zygote fork而来,具有相同的基址,攻击者通过分析自己进程的map文件(位于/proc/maps)就可以知道system_server以及所加载模块的内存布局。Google发布的补丁为java.io.InputStream添加了序列化检查来阻止攻击者发送android.os.BinderProxy,但通过这个漏洞我们可以发现一个可序列化的类只要满足以下条件就能代替android.os.BinderProxy实现代码执行的目的:

(1)实现了finalize方法;

(2)在finalize方法里调用了一个native指针;

(3)该native指针是攻击者可控的(没有被声明为transient和static);

(4)implements了Serializable接口(可序列化);

(5)没有重载readObject和readResolve方法来阻止我们控制native指针。

IBM Security在安卓原生框架中找到了一个这样的类OpenSSLX509Certificate(CVE-2015-3525),在Google Play Services APK中就使用了OpenSSLX509Certificate类。另外还发现了6 个存在漏洞的第三方SDK:

  • Jumio (CVE-2015-2000)
  • MetaIO (CVE-2015-2001)
  • PJSIP PJSUA2 (CVE-2015-2003)
  • GraceNote GNSDK (CVE-2015-2004)
  • MyScript (CVE-2015-2020)
  • esriArcGis (CVE-2015-2002)

那么这些SDK是否存在某些相似之处呢?经过分析发现前5个都使用了SWIG,这是一种连接C/C++与Java等各种高级语言的互操作性工具。在某些开发者提供的配置中,SWIG可以产生以下漏洞代码:

因为Bar能够被序列化,所以Foo可以被序列化,因此,攻击者可以控制swigCPtr(和swigCMemOwn),而swigCPtr被用于native代码中。因而这是一个高度符合条件可被利用的场景,特别是当原始的C++类有虚拟析构函数的时候。

通过分析这个漏洞我们可以知道,CVE-2014-7911的补丁只是紧缩了攻击界面,而没有真正解决问题。Google随后发布了CVE-2015-3525的补丁,将存在于OpenSSLX509Certificate类中的native指针声明为transient,使该指针不可被序列化。然而,即使安卓的原生世界修复了所有危险的可序列化类,如果第三方SDK中存在这样的类依然可被用于序列化攻击。IBM Security建议将Bundle的解析内部资源修改为懒行为,并修改readObject、readResolve等读取方法来阻止攻击者控制危险变量。

参考文章:

https://github.com/retme7/CVE-2014-7911_poc

http://researchcenter.paloaltonetworks.com/2015/01/cve-2014-7911-deep-dive-analysis-android-system-service-vulnerability-exploitation/

http://www.freebuf.com/news/74676.html

安卓序列化漏洞 —— CVE-2015-3525的更多相关文章

  1. php序列化漏洞理解

    0x01什么是序列化 序列化就是将我们的 对象转变成一个字符串,保存对象的值方便之后的传递与使用. 0x02为什么要序列化 如果为一个脚本中想要调用之前一个脚本的变量,但是前一个脚本已经执行完毕,所有 ...

  2. Typecho-反序列化漏洞学习

    目录 Typecho-反序列化漏洞学习 0x00 前言 0x01 分析过程 0x02 调试 0x03 总结 0xFF 参考 Typecho-反序列化漏洞学习 0x00 前言 补丁: https://g ...

  3. Apache ActiveMQ序列化漏洞(CVE-2015-5254)复现

    Apache ActiveMQ序列化漏洞(CVE-2015-5254)复现 一.漏洞描述 该漏洞源于程序没有限制可在代理中序列化的类.远程攻击者可借助特制的序列化的java消息服务(JMS)Objec ...

  4. 从watevrCTF-2019:Pickle Store中学习python之pickle序列化漏洞

    从watevrCTF-2019:Pickle Store中学习python之pickle序列化漏洞 pickle提供了一个简单的持久化功能.可以将对象以文件的形式存放在磁盘上. 其本质是Picklin ...

  5. 独家分析:安卓“Janus”漏洞的产生原理及利用过程

    近日,Google在12月发布的安卓系统安全公告中披露了一个名为"Janus"安卓漏洞(漏洞编号:CVE-2017-13156).该漏洞可以让攻击者绕过安卓系统的signature ...

  6. 应用安全-软件安全-漏洞CVE整理

    jira ssrf CVE-2019-8451 url = url + '/plugins/servlet/gadgets/makeRequest?url=' + host + '@www.baidu ...

  7. pikachu-反序列化漏洞

    1.序列化的概念(摘自pikachu平台的介绍) (1)序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:   class S{ public $te ...

  8. qemu毒液漏洞分析(2015.9)

    0x00背景 安全娱乐圈媒体Freebuf对该漏洞的有关报道: 提供的POC没有触发崩溃,在MJ0011的博客给出了修改后可以使qemu崩溃的poc.详见: http://blogs.360.cn/b ...

  9. CVE-2014-1767 漏洞分析(2015.1)

    CVE-2014-1767 漏洞分析 1. 简介 该漏洞是由于Windows的afd.sys驱动在对系统内存的管理操作中,存在着悬垂指针的问题.在特定情况下攻击者可以通过该悬垂指针造成内存的doubl ...

随机推荐

  1. 使用轻量级ORM Dapper进行增删改查

      项目背景 前一段时间,开始做一个项目,在考虑数据访问层是考虑技术选型,考虑过原始的ADO.NET.微软的EF.NH等.再跟经理讨论后,经理强调不要用Ef,NH做ORM,后期的sql优化不好做,公司 ...

  2. Python框架之Tornado(四)源码之褪去模板外衣

    上一篇介绍了客户端请求在tornado框架中的生命周期,其本质就是利用epoll和socket来获取并处理请求.在上一篇的内容中,我们只是给客户端返回了简单的字符串,如:“Hello World”,而 ...

  3. untiy数据包的输出、加载和卸载

    1:untiy数据包的输出: BuildPipeline.BuildAssetBundle将任意类型的资源打包成AssetsBundle文件. BuildPipeline.BuildAssetBund ...

  4. Goodchild教授关于GIS的四大预测的不同看法

    Goodchild教授的关于GIS的4个未来发展的预测不断有人在微信朋友圈里转发,虽然现在做的工作GIS只是一个基本的工具之一了,但对这4个预测还是有不少不同看法和一点自己的意见. Goodchild ...

  5. TL-WR702N 连接有线路由

    2015-12-23日 备忘录: 1. TL-WR702N一定要设置为 route模式,一定选择“动态ip”,而不是“PPPOE” 2.有线路由器 与  TL-WR702N 的IP不能在一个网段: 目 ...

  6. react native TypeError network request failed

        如果使用fetch获取数据,用的是POST方法,注意headers要添加请求头.当请求为GET时不能用body,当为POST时必须包含body,设置头部之后就一切正常了.   fetch(&q ...

  7. PHP —— 读取文件到二维数组

    转自:PHP读取自定义ini文件到二维数组 读取文件,可以使用file_get_contents,file,parse_ini_file等,现在有一个需求,需要读取如下格式的文件: [food] ap ...

  8. MongoDB副本集配置系列八:MongoDB监控

    1:Mongostat MongoDB2.6版本 MongoDB3.0版本 2:db.setProfilingLevel(2):打开profiler 类似于MySQL的slow log Profile ...

  9. JAVA自已设计JSON解析器

    当然,有很多很好的JSON解析的JAR包,比如JSONOBJECT,GSON,甚至也有为我们测试人员而打造的JSONPATH,但我还是自已实现了一下(之前也实现过,现在属于重构). 思想是这样的,以这 ...

  10. 导出Redis某个列表所有数据的语句

     echo "smembers done:www.huaihua.gov.cn" | redis-cli -h 127.0.0.1  >> /home/dz/fkw.d ...