2013年7月,安全组织Security Explorations发现了Java 7u25中的一个安全漏洞,通过这个漏洞攻击者可以完全摆脱Java沙箱。Oracle在更新的7u40中包含了一个补丁,但是据Security Explorations 在今年早些时候声称,这个补丁仅仅在理念上对其进行了修正,对代码稍加修改之后,依然可以利用这个漏洞。另外,随后的研究表明这个漏洞甚至比最初报道的更加严重。在这个问题公开之后,Oracle发布了一个补丁,作为8u77的一部分。

这个漏洞可以在新的反射库中找到,该库从Java 7以后均可以使用,更具体来讲,是在使用新的MethodHandle类动态访问和调用方法的时候。它与不同ClassLoader加载类的方式有关。要理解这个问题,需要一些基本的知识,这些知识涉及到Java ClassLoader的工作方式, 因为类加载是在Java中大家了解最少的领域之一,所以在阐述这个问题本身之前,我们会首先概述一下这个理念。

Java ClassLoader

Java能够在运行时从各种来源动态加载代码。这种功能是通过一系列名为ClassLoader的特殊类来实现的。标准的Java实现会提供多个ClassLoader来加载类,它们能够从文件系统、URL或压缩文件等位置加载类,不过Java也为开发人员提供了创建自定义ClassLoader的能力,以应对个性化的需求。与ClassLoader交互的常见方式是调用其loadClass(String)方法,这个方法会接受类的名称,如果能够找到的话,就会返回相关的Class对象,如果找不到的话,就会抛出ClassNotFoundException异常。在Java应用中的每个类都是通过某个ClassLoader按照这种方式加载的。

通过设置父ClassLoader,这些不同的ClassLoader能够互相连接起来,形成一个层级的结构。如果没有设置父ClassLoader的话,那么父ClassLoader默认将会设置为加载该ClassLoader的那个类加载器(ClassLoader本身也是类,因此也需要通过某个ClassLoader来进行加载)。如果提供了父ClassLoader的话,那么ClassLoader的默认行为就是将加载所请求类的任务委托给它的父加载器,只有父加载器(或祖父加载器)无法加载这个类的时候,这个ClassLoader本身才会试图加载所请求的类。但是,自定义加载器的创建者并非强制性要求遵循这种默认行为,他们完全可以选择实现不同的行为。

当Java应用启动的时候,如下的ClassLoader将会按照顺序发挥作用:

  1. Bootstrap ClassLoader:JVM本身的一部分,因此在每个JVM中,它的实现都是特有的。这个ClassLoader没有父ClassLoader,它用于加载java.lang包下的核心类。
  2. Extension ClassLoader:负责加载扩展库中的类,在每个Java安装环境下可能会有所差别。Extension ClassLoader将会加载java.ext.dirs变量所指定路径下的所有内容。
  3. Application ClassLoader:负责加载应用程序的主类以及所有位于应用类路径下的类。
  4. Custom ClassLoader:应用程序中使用的所有其他的ClassLoader。它是可选的,根据应用的情况不同,它可能并不存在。

在运行时,使用自定义的ClassLoader动态加载类为很多的应用创造了可能性,否则的话,有些功能可能是无法实现的,不过,遗憾的是,它也造成了很多的安全问题,尤其是在类仿造(class impersonation)方面。理论上,开发人员可以创建一个自定义的ClassLoader,让它来加载原始类java.lang.Object的一个模拟实现,并在应用程序中使用这个自定义的对象。这可能会在两个方面引发安全问题:这个自定义的对象能够访问java.lang包下所有包范围内可见的类内容;其次,这个自定义的Object会被JVM作为标准的Object对象,因此会将其作为由Java实现的可信任的类。

为了保护Java以应对这些安全问题,Java类要通过三个属性来进行识别:类名、包以及ClassLoader的引用。如果两个不同的类具有相同的类名和包名,但是由不同的ClassLoader所加载的话,Java会认为它们是不相等的,在它们两者之间进行赋值的话,将会导致ClassCastException异常。这样的话,就能保护环境免受类仿造的攻击。

部分修复以及由此导致的漏洞

Security Explorations最早报告了这个漏洞,并将其归类为CVE-2013-5838,这个漏洞可以描述为,当通过Method Handle调用方法时,对于被调用方法的那个类,它的ClassLoader并没有进行检查,这意味着攻击者可以按照上文所述的方法进行类的仿造。

展现原始漏洞的代码样例,目标类的ClassLoader并没有进行检查;来源:Security Explorations

Oracle在2013年9月提供了一个修正,作为Java 7u40的一部分,包含了类可见性的检查,它会对比预期类型和传入类型的ClassLoader,对比方式如下:

  • 如果两个ClassLoader相同的话,那么按照定义这两个类型是完全兼容的;
  • 如果其中一个ClassLoader是另一个ClassLoader的父加载器,那么它认为这两个类是通过正常的ClassLoader层级结构加载的,因此将其视为相等是安全的。

在第二项检查中,Security Explorations发现exploit稍加修改就可能继续有效。首先,用于仿造类的自定义ClassLoader将目标ClassLoader设置为它的父类加载器,这可以通过API以参数的方式进行设置:

URLClassLoader lookup_CL = URLClassLoader.newInstance(urlArray, member_CL);

通过该机制将自定义的ClassLoader作为等级结构的一部分,来源:Security Explorations

然后,鉴于ClassLoader的默认行为是将加载类的任务委托给它的父加载器,攻击者就需要确保父ClassLoader无法加载到这个类,这样他们自定义的ClassLoader就能发挥作用了。借助Java以网络方法加载类的过程,这种攻击模式得到了印证:如果这个类通过URL位置的方式来进行定义的话,父ClassLoader将会试图连接相关的服务器并获取这个类的代码,此时,预先构建好的HTTP服务器可以返回404 NOT FOUND错误,让父ClassLoader加载这个类出现失败,因此就会将控制权转移给自定义的ClassLoader。

通过自定义的HTTP服务器,强制父ClassLoader加载类失败之后的代码流,来源:Security Explorations

当这个缺陷2016年3月重新爆出时,当时最新的可用版本是8u74,这个版本被证明是有漏洞的,Oracle在8u77中为其提供了修正。但是,在8u77的发布说明中,这个漏洞依然描述为“会影响桌面设备上,Web浏览器中所运行的JavaSE[并且]不会影响到Java部署环境,比如典型的服务器或独立部署的桌面应用”,但是事实证明,它还是会影响服务器配置以及Google App Engine的Java环境。

修正:2016年4月29日

本文错误地认为这个漏洞在8u77、8u91和8u92版本中依然存在,实际上,在8u77中它已经得到了修正。在8u77的发布说明中将其描述为对CVE-2016-0636的修正,具体描述是这样的“未指明的漏洞[...]借助Hotspot子组件中未知的感染内容”并且没有包含对本文中所提及的CVE-2013-5838的明确引用。但是,Security Explorations指出 CVE-2016-0636是针对Issue 69的一个CVE编号,而Issue 69是他们自己代指最初CVE-2013-5838的一种方式。(在本文英文原文的评论区,讨论了该问题解决的相关过程,感兴趣的读者可以访问原文查看。——译者注)

查看英文原文:Vulnerability in Java Reflection Library Fixed after 30 Months

http://www.infoq.com/cn/news/2016/05/java-reflection-vulnerability?utm_campaign=rightbar_v2&utm_source=infoq&utm_medium=news_link&utm_content=link_text

Java反射库中的安全漏洞在30个月后终于修复了(转)的更多相关文章

  1. JAVA链表中迭代器的实现

    注:本文代码出自<java数据结构和算法>一书. PS:本文中类的名字定义存在问题,Link9应改为Link.LinkList9应该为LinkList.由于在同包下存在该名称,所以在后面接 ...

  2. Java开发中的eclispe常用快捷键&全部快捷键

    Java开发中的eclispe常用快捷键&全部快捷键 Ctrl+1 快速修复(经典快捷键)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ ...

  3. ref:关于JAVA中一些安全漏洞示例说明及如何规避方法代码示例总结分享

    ref:http://www.xwood.net/_site_domain_/_root/5870/5874/t_c268166.html 标签:安全,漏洞,健壮,java,SQL注入,SS及CSRF ...

  4. java代码审计中的一些常见漏洞及其特征函数

    文章来源:https://xz.aliyun.com/t/1633 最近在先知上看到之前有篇关于java代码审计的文章总结的蛮好,记录以下特征函数,方便查阅,同时自己也会将在平时代码审计过程中积累的函 ...

  5. Java语言中的面向对象特性总结

    Java语言中的面向对象特性 (总结得不错) [课前思考]  1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类?  2. 面向对象编程的特性有哪三个?它们各自又有哪些特性?  3. 你知 ...

  6. Linux上从Java程序中调用C函数

    原则上来说,"100%纯Java"的解决方法是最好的,但有些情况下必须使用本地方法.特别是在以下三种情况: 需要访问Java平台无法访问的系统特性和设备: 通过基准测试,发现Jav ...

  7. Java线程中yield与join方法的区别

    长期以来,多线程问题颇为受到面试官的青睐.虽然我个人认为我们当中很少有人能真正获得机会开发复杂的多线程应用(在过去的七年中,我得到了一个机会),但是理解多线程对增加你的信心很有用.之前,我讨论了一个w ...

  8. 如何在Java 8中愉快地处理日期和时间

    Java 8新增了LocalDate和LocalTime接口,为什么要搞一套全新的处理日期和时间的API?因为旧的java.util.Date实在是太难用了. java.util.Date月份从0开始 ...

  9. 找出Java进程中大量消耗CPU

    原文:https://github.com/oldratlee/useful-shells useful-shells 把平时有用的手动操作做成脚本,这样可以便捷的使用. show-busy-java ...

随机推荐

  1. hdu 2757 Ocean Currents(优先队列+bfs)

    小伙伴们真心被这道题惊呆了!刚开始是读题,题目都把小伙伴惊呆了,题目都读不懂! 在前面猴子小伙伴的帮助下,理解了一点点,又偷偷的在纸上写写画画,明白了题意! 后来,你懂的,果断拿下!在拿下的过程也经过 ...

  2. Flowers(二分水过。。。)

    Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  3. TROUBLE SHOOTING: FRM-30425

    关键字:Oracle Form buider FRM-30425 汇总 错误信息如下: FRM-30425: Summarized database item must reside in a blo ...

  4. 打开sa属性报错

    --如果打开sa属性报错如下:无法显示请求的对话框.属性IsLocked不可用于“登录名sa".该对象可能没有此属性,也可能是访问权限不足而无法检索 --解决办法:首先用windows登录, ...

  5. 高级UIKit-08(TCPSocket)

    [day1001_MoviePlayer]:视频播放 需要导入MediaPlayer.framework - (void)viewDidLoad { [super viewDidLoad]; NSUR ...

  6. 10-UIKit(UIDatePicker、UIPickerView、UIWebView、Storyboard)

    目录: 1. UIDatePicker 2. UIPickerView 3. UIPickerView多列关联 4. UIWebView 5. Storyboard(故事板) 回到顶部 1. UIDa ...

  7. Jquery学习笔记: attr和 prop的区别,以及为html标签自定义属性

    一.自定义html标签属性 对于html文件中的html标签,可以自定义属性,如: <a href="#" id="link1" action=" ...

  8. Java的位运算符具体解释实例——与(&amp;)、非(~)、或(|)、异或(^)

    位运算符主要针对二进制,它包含了:“与”.“非”.“或”.“异或”.从表面上看似乎有点像逻辑运算符,但逻辑运算符是针对两个关系运算符来进行逻辑运算,而位运算符主要针对两个二进制数的位进行逻辑运算.以下 ...

  9. IOS之【属性列表】

    @implementation JamesWongViewController - (void)viewDidLoad { [superviewDidLoad]; [selfwritePerson]; ...

  10. Use GraceNote SDK in iOS(二)获取音乐的完整信息

    在需求彻底明朗化,外加从MusicFans转到GraceNote,再从GraceNote的GNSDK转到iOS SDK后,最终完毕了在iOS上通过音乐的部分信息获取完整信息的功能了.(好吧,我承认是相 ...