导语:在一个星期前,我发布了一个工具,之前我一直在研究安全专家如何能够与使用了Java的远程方法调用(RMI)的应用程序进行交互。这是系列博客文章中的第一篇,本文主要阐述了RMI的安全性和我发布的工具BaRMIe。
在一个星期前,我发布了一个工具,之前我一直在研究安全专家如何能够与使用了Java的远程方法调用(RMI)的应用程序进行交互。这是系列博客文章中的第一篇,本文主要阐述了RMI的安全性和我发布的工具BaRMIe。
该工具的源代码以及二进制版本可以在GitHub上找到。幻灯片是我在44CON 2017中的演讲,我介绍了我的研究成果,PPT可以在SlideShare上找到。
为什么?
“RMI已经过时”
“那还是个事儿吗?”
“没有人再使用RMI”
当nmap报告“rmiregistry”服务时,那是我第一次遇到RMI 。我认为单独的远程方法调用听起来像是值得进一步研究的东西,但是没想到这个服务竟然很容易被攻击。根据RMI客户端的JAR文件编译了几行代码就完成了客户端的工作,RMI服务给了我对服务器文件系统(列表,读取,写入和删除文件)的未经验证的访问权限。让我感到惊讶的是,这是多么容易就能做到的啊,我想知道RMI已经多久被如此不安全地使用了,以及我可以用它能做些什么。
RMI安全
我最初的研究很快就发现了有很多RMI被不安全地使用着。这个问题的一个关键部分似乎是RMI是为了特定目的而构建的:在另一个Java虚拟机(JVM)中调用Java方法。这不是建立在安全的考虑之上的。我们可以把这个比喻成HTTP,只不过HTTP用户基础更加成熟。随着时间的推移,对安全性的需求已经导致HTTP不断发展以支持更可靠的安全性。现代Web开发人员甚至不需要特别的安全意识,因为应用程序框架在默认情况下会提供安全功能。RMI没有这个功能。此外,RMI的实现非常简单和透明,开发人员甚至不需要意识到它们正在与远程服务器交互。
RMI协议没有标准的安全功能。需要额外的工作来将诸如认证和会话管理之类的安全功能结合到通过RMI公开的类/对象之前。
攻击RMI
我对RMI服务发起的第一次攻击需要针对原始的客户端应用程序的JAR文件代码进行编译。我对此并不是很满意,我真正想要的是一个零知识攻击,这是我开始研究协议的原因之一。后来我遇到了Adam Boulton在AppSec USA 2008上的演讲 – 安全评估Java RMI– 他谈到了针对RMI服务的零知识攻击。不幸的是,这种攻击依赖于网络上的大量粗暴行为。
在没有实际的零知识攻击的情况下,我们需要远程类的详细信息,包括方法名称,参数类型和返回类型,以便与RMI服务进行交互。BaRMIe的目标是建立一套通过RMI公开的公共类和方法。使用这个工具,我们可以枚举一个RMI端点来识别已知的类并使用它们来攻击这个服务。
BaRMIe支持三种针对RMI服务的攻击:
1. 不安全的方法: RMI服务经常暴露一些危险的功能,可以直接调用已知的提供类/方法的细节。例如包括未经身份验证的文件读取和写入。
2. 通过对象类型参数 反序列化: RMI使用Java序列化使其成为反序列化攻击的目标。如果一个远程方法接受一个“java.lang.Object”类型的参数, 那么它可以被用来传递一个反序列化有效载荷。
3. 通过非法的方法调用进行反序列化:在对所提供的方法参数进行反序列化之前,Java不验证提供的方法参数是否与实际的方法参数类型兼容。这种弱点意味着任何非原始的远程方法参数都可以用TCP代理替换为任意对象,除非在Java未能执行非法方法调用之前触发反序列化有效载荷,否则将触发非法方法调用。
每个攻击都使用最小的RMI类和接口来实现,这些接口允许BaRMIe调用目标远程方法。BaRMIe还包括了TCP代理的代码,以 支持在网络层面注入有效负载的反序列化攻击。
在下一篇关于BaRMIe的博客文章中,我将详细介绍技术方面的一些东西,并介绍BaRMIe用来枚举和攻击RMI服务的一些代码和技术。