-
-
[翻译]思科Catalyst交换机 RCE 漏洞利用证明(CVE-2017-3881)
-
发表于: 2017-4-13 15:05 7222
-
思科Catalyst交换机 RCE 漏洞利用证明(CVE-2017-3881)
你依然允许你的Catalyst交换机使用telnet吗?三思啊,朋友,这篇文章是思科具备最新建议固件版本的Catalyst 2960交换机的远程代码执行利用(RCE)的证明。完整利用代码在这里。接下来的内容是对2017年3月7日CIA泄漏的漏洞利用开发过程的详细说明,并由思科于2017年3月17日公开披露。在本篇文章写作之时尚无可用的补丁。尽管如此,还有一个补救办法 - 禁用telnet并使用SSH。
CIA的一系列文件于2017年3月7日被泄露并且被发布在WikiLeaks。在其他的发布版本中有一个有趣的预验证代码执行漏洞影响了多个类型的思科交换机。该漏洞在泄漏的文档中的代号为ROCEM。虽然提到的技术细节很少,但是有几点却脱颖而出。
Vault 7文档揭示了实际漏洞利用的测试过程。此次泄露中并没有出现漏洞利用的源代码。这里突出显示了两个用例:该工具可以以交互模式或设置模式启动。交互模式通过telnet发送有效载荷,并在相同的telnet连接的上下文中立即向攻击者提供命令shell。[文档引用]:
设置模式。修改交换机的内存以此来完成后续的无密码telnet连接。[文档引用]:
在研究此漏洞时,有一项对我有用的信息,就是telnet调试输出,[文档引用]:
请注意最后一行的通过telnet服务接收的CISCO_KITS
选项。这被证明是一个重要的字符串。
思科于2017年3月17日披露了其交换机中存在的漏洞。该披露基于Vault 7中的文档:
Cisco IOS和Cisco IOS XE软件中的思科集群管理协议(CMP)处理代码中的漏洞可能允许未经身份验证的远程攻击者重新加载受影响的设备,或者以提升的权限远程执行代码。
撰写本文时没有提供太多细节,但下列内容除外:
集群管理协议在内部使用Telnet作为集群成员之间的信令和命令协议。 这个漏洞是由于两个因素的结合:
长话短说,漏洞允许攻击者利用telnet服务在目标交换机上获得远程代码执行权限。但是想要更好的利用该报告,我需要更多的信息。所以我决定深挖一下思科集群管理协议。
正好,我有两台Catalyst 2960交换机来研究该漏洞。集群管理协议设置了交换机之间的主从关系。主交换机可以在从属交换机上获得命令行shell的权限。正如思科在报告中提到的,telnet被用作集群成员之间的命令协议。有关群集的信息可以在这里找到,设置集群环境的例子在这里。
现在来查看一下集群之间的通信。以下是主交换机的配置:
该配置将会将附近的一个交换机作为从属机。rcommand <num>
允许从主接口的从设备上获取命令接口。正如预期的设计。
我们来看看rcommand
生成的流量:
见鬼了,该死的telnet流量呢?报告中明明清楚的写了啊:
集群管理协议在内部使用Telnet作为集群成员之间的信令和命令协议。
好吧,先运行一下show version
来查看一下更多的信息:
啊哈,Telnet流量实际上被封装在 Layer 2 LLC数据包中。如果看的足够仔细的话,我们将在源和目的地字段中注意到碎片化的MAC地址内的IP数据包。在这些“IP”数据包之内,存在具有telnet会话的有效TCP帧。
telnet会话通常在协商telnet选项之前。 其中包括:终端大小,终端类型等。请查看RFC了解更多信息。
在提交欢迎catalyst2>
消息之前,一个有趣的telnet选项被传输到服务器端:
在这里,你可以看到从主交换机发送到从交换机的telnet选项“CISCO_KITS”。在执行利用期间,这和Vault 7文档中出现字符串几乎相同。是时候深入来看看交换机内部了。
固件被存储在交换机中的flash:<version>.bin。
内置的ftp客户端允许将此固件传输到任意ftp服务器。妥了,现在要用binwalk分析和提取文件的内容:
为了方便对所得到的二进制数进行静态分析,我们最好知道固件加载偏移。在引导过程中,该偏移将打印到串行控制台:
启动IDA,嘀嘀嘀,开车了!CPU架构是PowerPC 32-bit BigEndian。在0x3000处加载bin:
还记得在之前捕获的集群流量中的CISCO_KITS
字符串吗?这将会是我的起点了。在IDA中探索了大多数函数之后,我已经可以看见固件中对该字符串的交叉引用了。
“CISCO_KITS”被return_cisco_kits
函数引用,该函数仅仅是返回了char*
。我们的着重点将会放在调用了return_cisco_kits
的0x0004ED8C
处的call_cisco_kits
上。
因为telnet代码对于客户端和服务器而言是相当对称的,我们实际上可以看到发送到服务器端的缓冲区的格式-%c%s%c%d:%s:%d:
。这实际上符合发送缓冲区\x03CISCO_KITS\x012::1:
的观测流量
注意到什么了没?有两个%s
格式符,但是实际上在流量样本中只有存在一个CISCO_KITS
字符串,第二个是空的并且被限制在另个:
之间。进一步观察相似功能的控制流程,注意到一些在处理第二个字符串时有趣的行为(这部分代码是服务器的部分):
我们在第二个%s字符串中发送的数据实际上被复制直到:
,并且没有检查目标缓冲区驻留在堆栈上的边界。这看起来像什么?没错,缓冲区溢出!
获取指令指针的控制很容易,因为它已被我发送的缓冲区(顺便说一句,我使用IOIDE调试)覆盖。问题在于堆和栈(驻留在堆中)没有执行权限。我敢打赌,这实际上是启用数据和指令缓存的效果。以下是Felix Lindner在BlackHat 2009上的演示文稿:
由于没有办法在堆栈上执行代码,所以我不得不将其用作数据缓冲区并重新使用固件中的现有代码。思路是将一系列函数的末尾有意义地链起来以执行任意内存写入。但是,等等,要写些什么?看看对0x00F47A34
处函数的反编译:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [翻译]一个简单虚拟机的逆向 10029
- [翻译]使用 IDAPython 写一个简单的x86模拟器 14916
- [翻译]通过x64分页机制的PTE Space实现内核漏洞利用 15863
- [翻译]Unicorn引擎教程 46328
- [翻译]首款反射式PE壳<琥珀>简介 19150