再黑Facebook!MobileIron MDM未授权远程代码执行漏洞分析

本文详细分析了MobileIron MDM系统中发现的未授权远程代码执行漏洞链,包括Hessian反序列化、JNDI注入绕过和GroovyShell利用等技术细节,最终实现在Facebook服务器上执行任意代码的全过程。

Orange:我是如何再次黑掉Facebook的!MobileIron MDM未授权RCE漏洞分析

作者:Orange Tsai
本文是DEVCORE的交叉发布博客。[中文版请参阅这里]

大家好,距离上一篇文章已经很久了。这篇新文章是关于我今年三月的研究,讲述了我如何在一个领先的移动设备管理(MDM)产品中发现漏洞,并通过绕过多个限制实现未授权远程代码执行(RCE)。所有漏洞都已报告给厂商并在6月修复。之后我们持续监控各大企业的修复进度,发现Facebook超过两周未打补丁,于是我们在Facebook服务器上获得了shell并报告给他们的漏洞赏金计划!

这项研究也在HITCON 2020上进行分享。幻灯片可在此查看

研究背景

作为红队成员,我们一直在寻找从外部渗透企业网络的新途径。就像我们去年在Black Hat USA上的研究一样,我们展示了如何黑掉主流SSL VPN设备并将其变成你的虚拟"公共"网络!SSL VPN被认为足够安全,是企业接入私有网络的唯一途径。但如果你信任的设备本身就不安全呢?

基于这个场景,我们希望探索企业安全的新攻击面,于是对MDM产生了兴趣,本文就是相关研究成果。

什么是MDM?

移动设备管理(Mobile Device Management, MDM)是一种资产管理系统,使企业能够更好地管理员工自带设备(BYOD)。它于2012年提出,以应对日益增长的平板和移动设备数量。MDM可以确保设备在受信任环境中运行,并符合企业策略。企业可以管理资产、安装证书、部署应用,甚至远程锁定/擦除设备以防止数据泄露。

统一终端管理(UEM)是与MDM相关的新术语,对管理设备有更广泛的定义。下文我们使用MDM来代表类似产品。

研究目标

MDM作为集中式系统,可以管理和控制所有员工设备,无疑是成长型企业的理想资产管理系统。此外,MDM必须公开可访问以同步全球设备。一个集中且公开暴露的设备,对黑客来说还有什么比这更有吸引力?

因此,我们看到近年来黑客和APT组织滥用MDM的案例!比如诱骗受害者使MDM成为其移动设备的C&C服务器,甚至直接入侵企业暴露的MDM服务器向所有设备推送恶意木马。你可以阅读Cisco Talos团队的《恶意MDM:让我们隐藏这个应用》和CheckPoint CPR团队的《首次在野发现-恶意软件利用企业MDM作为攻击载体》获取更多细节。

从前述案例中,我们知道MDM是黑客的绝佳目标,因此决定对其进行研究。市场上有多种MDM解决方案,甚至微软、IBM和苹果都有自己的MDM产品。我们该从哪个开始?

我们列出了已知MDM解决方案并扫描了互联网上的相应模式,发现最流行的MDM是VMware AirWatch和MobileIron!

那么为什么选择MobileIron作为目标?根据其官网,超过20,000家企业选择MobileIron作为MDM解决方案,我们的多数客户也在使用它。我们还知道Facebook自2016年起就暴露了MobileIron服务器。我们分析了《财富》全球500强企业,发现超过15%使用并将MobileIron服务器暴露在公网!基于这些原因,它成为了我们的主要目标。

研究起点

从过去的漏洞来看,研究MobileIron的安全人员并不多。也许攻击向量尚不明确。但我们怀疑主要原因是固件太难获取。在研究设备时,将纯黑盒测试转为灰盒或白盒测试至关重要。我们花费大量时间在互联网上搜索各种信息,最终找到一个RPM包。这个RPM文件应该是开发人员的测试包,它就放在一个可列出的Web根目录下并被Google索引。

无论如何,我们得到了一个研究文件。该文件的发布日期是2018年初,虽然有点旧但总比没有好!

漏洞发现

经过痛苦的依赖地狱解决过程,我们终于搭建起了测试环境。该组件基于Java并开放三个端口:

  • 443 - 用户注册接口
  • 8443 - 设备管理接口
  • 9997 - MobileIron设备同步协议(MI协议)

所有开放端口都经过TLS加密。Web部分前端是Apache,将所有连接代理到后端——一个运行Spring MVC的Tomcat。

由于使用了Spring MVC,很难从单一视角找到传统漏洞如SQL注入或XSS。因此,这次我们的目标是检查逻辑和架构!

说到漏洞,根本原因很简单。Tomcat暴露了一个Web服务,该服务使用Hessian格式反序列化用户输入。但这并不意味着我们可以为所欲为!本文的主要努力就是解决这个问题,请见下文利用细节。

虽然我们知道Web服务会反序列化用户输入,但我们无法触发它。端点位于两个位置:

  1. 用户注册接口 - https://mobileiron/mifs/services/
  2. 管理接口 - https://mobileiron:8443/mics/services/

我们只能通过管理接口触及反序列化,因为用户接口阻止了Web服务访问。这对我们是个重大打击,因为大多数企业不会将管理接口暴露在互联网上,仅限管理接口的漏洞对我们没什么用,所以必须更加努力:(

仔细检查架构后,我们发现Apache通过重写规则阻止了我们的访问。看起来不错,对吧?

1
2
RewriteRule ^/mifs/services/(.*)$ https://%{SERVER_NAME}:8443/mifs/services/$1 [R=307,L]
RewriteRule ^/mifs/services [F]

MobileIron依赖Apache重写规则来阻止所有对Web服务的访问。它位于反向代理架构的前端,后端是基于Java的Web服务器。这让你想起什么了吗?

是的,就是"解析逻辑绕过"!这是我在2015年提出的反向代理攻击面,并在Black Hat USA 2018上分享。该技术利用Apache和Tomcat之间的不一致性绕过ACL控制重新访问Web服务。顺便说一句,这个优秀的技术也应用于最近的F5 BIG-IP TMUI RCE漏洞

1
https://mobileiron/mifs/.;/services/someService

漏洞利用

好了,现在我们可以在注册接口或管理接口上访问反序列化了。让我们回到利用部分!

Moritz Bechler有一项很棒的研究,在他的白皮书《Java反序列化安全》中总结了Hessian反序列化漏洞。从marshalsec源代码中,我们了解到Hessian反序列化在重建HashMap时会触发equals()和hashcode()。它也可以通过XString触发toString(),目前已知的利用链有:

  1. Apache XBean
  2. Caucho Resin
  3. Spring AOP
  4. ROME EqualsBean/ToStringBean

在我们的环境中,我们只能触发Spring AOP利用链并获得JNDI注入。

名称 效果
× Apache XBean
× Caucho Resin
Spring AOP
× ROME EqualsBean

一旦有了JNDI注入,剩余的利用部分就简单了!我们可以直接利用Alvaro Muñoz和Oleksandr Mirosh在Black Hat USA 2016上的工作《从JNDI/LDAP到远程代码执行梦想之地的旅程》来获取代码执行…真的是这样吗?

自从Alvaro Muñoz和Oleksandr Mirosh在Black Hat上介绍这项技术以来,可以说它帮助了无数安全研究人员,并将Java反序列化漏洞带入了一个新时代。然而,Java最终在2018年10月修复了JNDI/LDAP拼图的最后一块。之后,所有高于8u181、7u191和6u201的Java版本都无法再通过JNDI远程URL类加载获得代码执行。因此,如果我们在最新的MobileIron上利用Hessian反序列化,就必须面对这个问题!

Java将com.sun.jndi.ldap.object.trustURLCodebase的默认值改为False,以防止攻击者下载远程URL类获取代码执行。但仅此而已。我们仍然可以操纵JNDI并将命名引用重定向到本地Java类!

这个概念有点类似于面向返回编程(ROP),利用本地现有的Java类进行进一步利用。你可以参考Michael Stepankin在2019年初的文章《利用Java中的JNDI注入》了解详情。它描述了后JNDI利用攻击以及如何滥用Tomcat的BeanFactory来填充ELProcessor利用链以获得代码执行。基于这个概念,研究员Welkin还提供了Groovy上的另一个ParseClass利用链。正如他在中文文章中所述:

“除了javax.el.ELProcessor,当然也还有很多其他的类符合条件可以作为beanClass注入到BeanFactory中实现利用。举个例子,如果目标机器classpath中有groovy的库,则可以结合之前Orange师傅发过的Jenkins的漏洞实现利用”

看来我之前在Jenkins研究中的元编程利用也可以在这里使用。这让元编程再次伟大起来:D

这个方法很棒,对我们来说看起来可行。但由于目标库版本过旧,ELProcessor和ParseClass两个利用链都不可用。Tomcat从8.5开始引入ELProcessor,但我们的目标是7。至于Groovy利用链,目标Groovy版本太旧(2008年的1.5.6)不支持元编程,所以我们仍然必须自己寻找新的利用链。最终我们在GroovyShell上发现了一个新的利用链。如果你感兴趣,可以查看我提交给JNDI-Injection-Bypass项目的Pull Request

攻击Facebook

现在我们有了一个完美的RCE利用链,结合了JNDI注入、Tomcat BeanFactory和GroovyShell。是时候黑掉Facebook了!

如前所述,我们知道Facebook自2016年起就使用MobileIron。虽然现在服务器索引返回403禁止访问,但Web服务仍然可访问!

万事俱备,只欠我们的漏洞利用!然而,在我们计划攻击的前几天,我们意识到漏洞利用中存在一个关键问题。从我们上次在Facebook上获取shell的经验中,我们注意到由于安全考虑,它阻止了出站连接。出站连接对JNDI注入至关重要,因为其核心思想是让受害者连接到恶意服务器以进行进一步利用。但现在我们甚至无法建立出站连接,更不用说其他了。

到目前为止,JNDI注入的所有攻击面都已关闭,我们别无选择,只能回到Hessian反序列化。但由于缺乏可用的利用链,我们必须自己发现一个新的!

在发现新的利用链之前,我们必须正确理解现有利用链的根本原因。重读Moritz Bechler的论文后,某个词引起了我的兴趣:

“无法恢复Groovy的MethodClosure,因为调用了readResolve()并抛出异常”

我脑海中很快浮现出一个问题:为什么作者要把这个词留在这里?尽管它因异常而失败,但一定有什么特别之处让作者记下这一点。

我们的目标运行着一个非常旧的Groovy,所以我们猜测readResolve()约束可能还没有应用到代码库中!我们比较了最新版和1.5.6版的groovy/runtime/MethodClosure.java文件。

1
2
3
4
5
6
7
8
$ diff 1_5_6/MethodClosure.java 3_0_4/MethodClosure.java

>     private Object readResolve() {
>         if (ALLOW_RESOLVE) {
>             return this;
>         }
>         throw new UnsupportedOperationException();
>     }

是的,我们是对的。Groovy 1.5.6中没有ALLOW_RESOLVE,后来我们了解到CVE-2015-3253就是针对这个问题的。这是2015年为应对日益增长的Java反序列化漏洞而采取的缓解措施。由于Groovy是一个内部使用的库,如果没有紧急情况,开发人员不会更新它。过时的Groovy也可以作为一个很好的案例研究,展示一个无害的组件如何让你被攻陷!

当然,我们最终在Facebook上获得了shell。以下是视频:

漏洞利用视频

漏洞报告与修复

我们在3月份完成了所有研究,并于4月3日向MobileIron发送了安全公告。MobileIron于6月15日发布补丁,并分配了三个CVE。你可以查看官方网站了解详情!

  • CVE-2020-15505 - 远程代码执行
  • CVE-2020-15506 - 认证绕过
  • CVE-2020-15507 - 任意文件读取

补丁发布后,我们开始监控互联网以跟踪整体修复进度。这里我们检查静态文件的Last-Modified头,因此结果仅供参考。(Unknown代表服务器关闭了443和8443端口)

同时,我们也持续关注Facebook。在确认15天未打补丁后,我们最终于7月2日获取shell并报告给他们的漏洞赏金计划!

结论

到目前为止,我们已经展示了MobileIron上一个完全未授权的RCE。从如何获取固件、发现漏洞,到绕过JNDI缓解措施和网络限制。还有其他故事,但由于时间关系,我们只列出以下主题供感兴趣的人参考:

  • 如何从MDM接管员工设备
  • 反汇编MI协议
  • 以及CVE-2020-15506,一个有趣的认证绕过

我希望这篇文章能引起人们对MDM和企业安全重要性的关注!感谢阅读。:D

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计