0x01 背景


今年8月, Shadow Brokers组织在其Twitter微博上公开了入侵NSA后获取的大量黑客工具,并将部分放在网上进行拍卖。根据Shadow Brokers描述,这些工具原属于著名的黑客团队方程式组织(Equation Group),思科的官方博客也在第一时间对该后门进行了简要分析,以下是思科官方博客给出漏洞和后门模块研究分析,360 MeshFire团队也第一时间对泄漏文件、0DAY漏洞和植入后门进行了深入研究和完整分析。

在该系列上一篇文章中我们主要针对EXTRABACON模块中Cisco ASA防火墙SNMP远程代码执行的0DAY漏洞(CVE-2016-6366),对产生原因和利用原理进行了详细分析。详见链接:

该漏洞实现了思科网络基础设施的破门并获取网络设备管理员权限,如何植入后门并实施更加隐蔽的后门攻击等攻击手段则是在EPICBANANA和JETPLOW的模块中实现,后门模块提供了更加复杂和隐蔽的攻击方法,我们将在该篇文章中详细分析ASA设备的后门原理和植入方法,并对后门连接作简单演示。

0x02 Cisco ASA后门简介


泄漏的文件中专门针对于Cisco ASA防火墙的后门可分为内存型和持久化型。从我们的分析看,内存型后门被命名为BANALRIDE和BANANAGLEE(简称BG),其中BANALRIDE只提供基本的控制功能和一些原始设备操作的API,而BG相对于BANALRIDE的功能更加强大和复杂;持久化后门又分为JETPLOW和SCREAMPLOW,其中JETPLOW作为早期的持久化后门主要针对于PIX防火墙和部分ASA设备,而新版本的被称为SCREAMPLOW是JETPLOW的升级版。

在整个后门植入过程中,首先需要利用命令解析漏洞(CVE-2016-6367),漏洞利用的前提是攻击者能够成功登录设备,可用已知用户名和密码登录,也可以利用漏洞修改登录流程实现任意账户名密码直接登录(见第一篇文章)。

然后执行e 脚本通过ssh或telnet登录到ASA系统,并发送payload至console终端,该脚本将构造15个攻击载荷到console终端下触发命令行解析漏洞,通过内存溢出的方式将BANALRIDE后门写入到ASA内存中。

最后使用目录下的bride-1120连接工具连接到BANALRIDE后门,BANALRIDE后门连接后的截图如下:

可执行的操作包括获取系统版本,内存操作申请、释放、读取和查看内存等,此外还可以植入控制接口更全面的BG后门(选项30)。

持久化后门JETPLOW和SCREAMPLOW也需要借助BG进行上传植入。但遗憾的是在这次泄露的文件中并没有包含BG后门的真实载荷,莫非在Shadow Broker拍卖转众筹文件里?即便没有BG载荷,我们通过加载错误的BG文件,还是可以显示后门主要功能,包括读配置信息、接口信息和ARP表信息,更全面的读写内存操作,更重要的是实现了模块化的加载持久后攻击后门。

0x03 BANALRIDE后门分析


因缺少BANANAGLEE后门载荷,也就无法成功植入持久化SCREAMPLOW后门,我们将重点对可实现完整连接的BANALRIDE后门载荷的运行原理进行动态分析,对持久化后门SCREAMPLOW只作静态分析。本文的调试环境基于Cisco ASA 5505型号ASA设备,系统镜像版本为a。

1. 后门初始化

当BANALRIDE初次植入,全部代码被分为14个片段离散分布在ASA网络处理主进程lina进程空间中。通过shellcode控制EIP跳转到第一处片段来执行初始化操作,此段代码块主要执行了两部分操作:

(1)解密自身代码

由于BANALRIDE代码经过加密后植入到lina进程中,所以在初始化代码起始处存在解密后续代码的过程:

12345678910111213 0xddfeb316: mov $0xaaaaaa82,%eax 0xddfeb31b: xor $0xaaaaaaaa,%eax 0xddfeb320: mov $0xddfeb314,%edi 0xddfeb325: add %eax,%edi 0xddfeb327: mov $0xaaaaaa74,%ecx 0xddfeb32c: xor $0xaaaaaaaa,%ecx 0xddfeb332: mov (%edi),%bl 0xddfeb334: xor $0x9c,%bl 0xddfeb337: mov %bl,(%edi) 0xddfeb339: inc %edi 0xddfeb33a: loop 0xddfeb332 0xddfeb33c: and $0x41622d98,%eax 0xddfeb341: pop %ds

在地址0xddfeb332~0xddfeb33a的代码通过异或方式循环解密了从0xddfeb33c起始的代码,在第一处解密后的代码中还存在解密其它地址段的代码片段。

(2)申请内存

将其它分散在lina进程中的后门代码全部copy拼接到新申请的内存中。由于lina进程通过思科自实现的内存池方式来管理内存,而ASA系统中大部分内存的动态申请也是依赖于内存池机制。此后门并没有直接调用glibc中的内存申请函数,而是也复用了lina进程中内存池操作函数sub_89BCE60来申请内存,代码如下:

12340xddfeb595: push $0x15500xddfeb59a: mov $0x89bce60,%eax0xddfeb59f: call *%eax0xddfeb5a1: mov %eax,%edi

在初始化代码中记录了所有分散的代码片段地址,如下所示:

1234567891011MEMORY:DDFEB5AE mov dword ptr [ebp-3Ch], 0DDFEB734hMEMORY:DDFEB5B9 mov dword ptr [ebp-38h], 0DDFEB944hMEMORY:DDFEB5C0 mov dword ptr [ebp-34h], 0DDFEBB54hMEMORY:DDFEB5C7 mov dword ptr [ebp-30h], 0DDFEBD64hMEMORY:DDFEB5CE mov dword ptr [ebp-2Ch], 0DDFEBF74hMEMORY:DDFEB5D5 mov dword ptr [ebp-28h], 0DDFEC184hMEMORY:DDFEB5DC mov dword ptr [ebp-24h], 0DDFEC394hMEMORY:DDFEB5E3 mov dword ptr [ebp-20h], 0DDFEC5A4hMEMORY:DDFEB5EA mov dword ptr [ebp-1Ch], 0DDFEC7B4hMEMORY:DDFEB5F1 mov dword ptr [ebp-18h], 0DDFEC9C4hMEMORY:DDFEB5F8 mov dword ptr [ebp-14h], 0DDFECBD4h

2. 网络通讯

ASA对所有网络报文的处理都是通过lina程序来驱动实现的,由于ASA底层Linux系统并不能识别ASA的硬件接口设备,因此无法在Linux系统层面完成网络数据层面的通信,也无法借助系统socket进行通信,只能复用lina进程空间中的网络通信函数。

(1)网络接收函数劫持

当后门程序完成初始化操作后会跳转到ASA系统正常程序流程,但后续为了能够接收攻击者连接指令,则还需开启网络接收功能,后门连接并未指定专用网络端口,因此必须监听所有端口上的数据流量,并从中筛选出连接指令。

在ASA系统主进程lina中,网络模块在处理数据报文时使用回调函数sub_8660C30来处理从物理网口接收到的每一个数据包。BANALRIDE可以通过劫持此函数,使正常的报文处理流程跳转到自身代码中,并从栈中取出报文地址,以达到劫持经过ASA网口所有流量的目的。实现HOOK网络接收程序代码如下:

1234567891011121314150xddfeb645: mov $0x916bbb0,%ebx……0xddfeb678: push $0xa0xddfeb67a: push %eax0xddfeb67b: push $0x807bef10xddfeb680: call *%ebx0xddfeb682: push $0xe0xddfeb684: lea -0x4c(%ebp),%eax0xddfeb687: push %eax0xddfeb688: push $0x80612c10xddfeb68d: call *%ebx0xddfeb68f: movb $0xe9,0x8660c930xddfeb696: mov $0x1,%eax0xddfeb69b: movl $0xffa00629,0x8660c94

其中0x916bbb0是ASA系统内存copy函数,将第二个参数指向地址copy到第一个参数指向内存中,长度由第三个参数控制。lina进程空间中代码段改动前后对比如下图所示:

BANALRIDE后门植入到内存中时修改sub_8660C30函数中0x08660C93地址处代码,使程序流程跳出当前函数。在地址0x80612c1处写入了进入后门代码区的跳转指令,其中0xC5514B68就是存放后门代码的地址,这个地址是变化的,由初始化阶段动态申请。最后在0x807bef1处写入了当BANALRIDE代码执行结束后返回sub_8660C30函数正常流程的跳转指令,整个跳转流程如下图:

在这个流程图中可以看到,其实BANALRIDE后门在内存中每次运行的生命周期为从接收到一个网络报文起,到处理这个报文结束为止。

(2)网络发送函数:

从代码中可看到BANALRIDE向控制端发送网络报文时复用lina函数的过程,首先调用sub_89BD690函数创建一个描述数据报文的结构变量,大小为0x60E(1550)字节,代码如下:

12345MEMORY:C551524E push 60EhMEMORY:C5515253 mov [ebp+var_10], eaxMEMORY:C5515256 mov eax, 89BD690hMEMORY:C551525B movzx edi, [ebp+arg_14]MEMORY:C551525F call eax

对sub_89BD690返回数据的结构进行分析结果如下:

123456789101112131415struct struc_send_pkt{ char unknow_str1[30]; char mac_src[6]; char mac_dst[6]; _WORD type; char vlan_tag[4]; char *p_ip_packet; char *p_Buff; char unknow_str2[4]; struc_send_udp_info *p_send_udp_info; char unknow_str3[728]; char ip_header[20]; char udp_header[8];};

可以看到此结构体中包含了发送数据包二层及三层报文头部各字段的详细信息,虽然sub_89BD690函数申请了1550字节长度的内存空间,但这个结构体只规定了此段内存前820字节长度的数据格式,之后剩余部分填充为程序自定义的载荷数据,因此对sub_89BD690函数传参不能小于820字节。

ASA系统中对于发送报文的函数封装并不如在Linux系统中的系统调用简单明了,考虑到在struc_send_pkt结构中还需要填充二层网络目的地址,因此需要在ASA路由表中查找出报文的下一跳地址:

1234MEMORY:C55151BA push esi ;bufferMEMORY:C55151BB mov eax, 8778AF0h ;route_table_lookupMEMORY:C55151C0 push [ebp+arg_8] ;dst ipMEMORY:C55151C3 call eax

sub_8778AF0函数查找出第一个参数指向的目的IP地址的下一跳IP,并将结果存放在第二个参数指向的地址中,返回结果是一个结构体,从起始偏移16字节为下一跳的IP,随后使用sub_84C0200函数在ARP表中查找出下一跳IP相应的MAC地址,再调用sub_84BE670函数将查询出的地址填充到struct_send_pkt中:

1234MEMORY:C55151CB push ediMEMORY:C55151CC mov eax, 84C0200hMEMORY:C55151D1 push dword ptr [esi+10h]MEMORY:C55151D4 call eax

最后将构造好的struc_send_pkt结构变量传递给sub_863FE50函数来构造完整的网络报文并添加到发送队列中:

1234MEMORY:C55151F6 mov eax, [edx+4]MEMORY:C55151F9 push [ebp+arg_0] ;struc_send_pktMEMORY:C55151FC push eaxMEMORY:C55151FD call dword ptr [eax+0Ch] ; 0x863FE50

(3)传输通信加密

BANALRIDE与控制端网络通讯时,在建立session阶段先使用Diffie-Hellman算法协商密钥,在此后的通讯中,所有数据都使用此密钥进行AES算法加密。当接收到控制指令时,会先判断有无session,代码如下:

123456MEMORY:C551570E mov edi, offset 0xC55CFC34MEMORY:C5515714 lea eax, [esi+14h] ; UDP报文指针MEMORY:C5515717 mov [ebp+var_10], eaxMEMORY:C551571A mov eax, [edi]MEMORY:C551571C cmp byte ptr [eax], 0 ; 判断sessionMEMORY:C551571F jz short loc_C551576F

若已存在session则会再判断与之前建立的session的连接四元组信息,若session尚未建立先判断接收payload第一个字符也就是控制指令是否为A8,表明是否建立新的session,代码如下:

12345678910MEMORY:C551576F mov edx, [ebp+var_10]MEMORY:C5515772 lea edi, [esi+1Ch]MEMORY:C5515775 movzx eax, word ptr [edx+4]MEMORY:C5515779 movzx ecx, alMEMORY:C551577C shl ecx, 8MEMORY:C551577F shr eax, 8MEMORY:C5515782 or ecx, eaxMEMORY:C5515784 lea eax, [ecx-8]MEMORY:C5515787 mov [ebp+var_14], eax ; payload长度MEMORY:C551578A cmp byte ptr [esi+1Ch], 0A8h ; 判断控制指令是否是0xA8

BANALRIDE会对接收到的payload进行完整性校验,具体方式通过计算比对payload最后两字节的校验和,验证通过后再计算加密密钥返回给控制端:

123456789MEMORY:C55157A4 call sub_C55156C0 ; a1:payload地址 a2:payload长度MEMORY:C55157A9 pop ecxMEMORY:C55157AA pop edxMEMORY:C55157AB xor edx, edxMEMORY:C55157AD test al, alMEMORY:C55157AF jz short loc_C55157CBMEMORY:C55157B1 push esiMEMORY:C55157B2 push ediMEMORY:C55157B3 call sub_C551581D ;

计算校验和处理流程见下图:

0x04 SCREAMPLOW持久化后门分析


第二节中我们介绍到SCREAMPLOW 作为持久化后门实际上是JETPLOW 升级版,后门程序在BANANAGLEEBG3121InstallLP目录下,先通过BPICKER-3100工具连接BG内存后门UDP500端口后,加载相关载荷模块植入到目标设备中,BPICKER-3100是writeScreamingPlow和writeJetPlow新版本,SCREAMPLOW种植持成功后也可使用lp工具对目标进行后续的连接和管理。

当BPICKER-3100与目标建立连接成功后,会收到目标返回的ASA系统和后门版本信息,然后在当前目录下搜索名称基于<platform_name>-moduledata-<bg_version>.tgz格式的文件,但目前泄露出的文件中只包含了唯一的版本:a。此文件中包含了种植SCREAMPLOW所需的载荷以及配置文件等。

对BPICKER-3100进行静态代码分析发现,在植入过程中,会对a文件中asa目录下的pif文件进行解密,其解密密钥通过硬编码方式写入在BPICKER-3100程序中,存储过程仅简单做了一次异或加密,获取密钥的相关代码如下:

123456789101112819 v2 = malloc(0x1Du); v3 = v2; v4 = v2 == 0; v5 = "Couldn't malloc for key_data_copy."; if ( v4 ) goto LABEL_6; *v3 = 0xC28AD3C7; v3[1] = 0xD8CFDCC5; v3[2] = 0xCCCBD8C9; v3[3] = 0xD9C38ADE; v3[4] = 0xC6DFCC8A; v3[5] = 0xCCC58AC6; v3[6] = 0xC6CFCF8A; *((_BYTE *)v3 + 28) = -39; v6 = 0; do *((_BYTE *)v3 + v6++) ^= 0xAAu; while ( v6 <= 28 );

解密后的明文密钥为:my hovercraft is full of eels。随后对于所有pif文件进行解密,命令如下:

1find . -iname "*.pif" -type f -print -exec sh -c 'openssl base64 -d -in {} | openssl aes-128-cbc -d -nosalt -md md5 -k "my hovercraft is full of eels" > {}.xml' ;

解密后的pif文件部分内容如下:

12345678910111281920212223242526272829303132<?xml version="1.0" encoding="iso-8859-1"?><platform xsi:noNamespaceSchemaLocation="ver; xmlns:xsi="; lib="liba;> <name>asa5505</name> <version> <name>1.0(12)6 (no persistence detected)</name> <originalBios>bin/asa5505/asa5505_10126_bios_sectors1-E_clean.bin</originalBios> <patchList><!-- Install SCP --> <patch> <data src="inline" type="userarea">0</data> <!-- Assigned later --> <address>fff70000</address> <!-- SECOND_USER_AREA_ADDRESS --> </patch> <patch> <data src="file">bin/asa5505/SCP28/asa5505_patch60000.bin</data> <address>fff60000</address> <!-- FIRST_CODE_AREA_ADDRESS --> </patch> <patch> <data src="inline" type="pbd">0</data> <!-- Assigned later --> <address>fff6df00</address> <!-- FIRST_USER_AREA_ADDRESS --> </patch> <patch> <data src="file">bin/asa5505/SCP28/asa5505_patchEC480.bin</data> <address>fffec480</address> <!-- SECOND_CODE_AREA_ADDRESS --> </patch> <patch> <data src="file">bin/asa5505/SCP28/asa5505_patchE18BF.bin</data> <address>fffe18bf</address> <!-- HOOK_ADDRESS --> </patch> </patchList> </version></platform>

此XML文件描述了SCREAMPLOW后门感染目标ROMMON版本为1.0(12)6的Cisco ASA 5505型号设备,而感染前的原始BIOS镜像文件存放在bin/asa5505,通过此XML文件可大致了解后门植入ASA 的BIOS内存中的代码区域,如下图所示:

SCREAMPLOW后门通过感染BIOS进程空间实现持久化,由于Cisco ASA设备在执行reload命令后内存中的BIOS代码并没有重新从文件中载入,因此通过reload重启的方式并无法彻底清除此后门。

0x05 通过BANALRIDE实现监听流量后门


对于网络设备后门攻击来说,实现流量监听和重定向是十分重要的环节,其中BANANAGLEE作为最核心的后门模块提供相关功能接口,但由于BANANAGLEE载荷缺失,并不能对其进行实际研究测试,但我们发现当前泄漏出来的BANALRIDE后门已经具备了BG的大部分网络后门功能,可以理解其是一个内存小马,BG是一个内存大马,若适当修改BANALRIDE中的部分代码实现完整的流量监听和重定向功能,便实现后门攻击的核心功能,以下示例中我们重现了通过BANALRIDE实现对HTTP报文的流量监听并将其重定向输出到设备文件中。

由于BANALRIDE后门劫持了ASA设备底层网络的所有流量,因此完全可以设置过滤规则并从中筛选出感兴趣数据,例如可以监听流经ASA物理网口上所有HTTP报文,并通过文件输出函数sub_8074498将报文输出到文本中,结果如下图所示:

可以充分发挥想象力,配合上一节所提到的lina中数据包发送功能函数将己截获的数据流量镜像发送到攻击者指定的IP上去,即实现流量重定向功能。

0x06结论


针对此次对Cisco ASA防火墙后门的深入分析,可以看出针对网络基础设施的攻击程序已经达到了相对较高的工程化实现,并实现了全平台多版本的适配,从研发和植入成本看需要具备相对较高的技术门槛。

1.ASA系统底层是Linux系统,但是无法通过传统Linux系统方式进行渗透。ASA设备网络通信使用的数据通信接口都是由lina进程驱动的,对所有网络报文的处理也通过lina程序来实现,底层Linux系统并不能识别ASA数据平面的网络接口,因此在整个后门代码中无法使用任何Linux系统调用包括socket程序来实现后门的核心网络功能,后门所有行为,包括加解密、内存管理、网络通讯等,都是复用了ASA主进程lina中函数指针。BANALRIDE通过劫持监听ASA系统中所有流量并从中过滤出控制命令。

2.通过对代码中调用函数进行分析,可以推测出后门研发组织对于ASA系统以及内部函数调用功能非常熟悉。我们发现在IDA中逆向的ASA系统中总包含近有四万个函数,且每个版本系统的函数地址都存在差异性,若仅通过逆向的方式来从中获取攻击过程中所需函数其工作量是巨大的,不排除后门研发组织对于ASA系统有更为充分的技术资料支持其研发。

3.ASA设备植入的后门具备非常高的隐蔽性。首先,该后门植入并没有在网络设备上开放任何TCP或UDP的网络监听端口,完全依靠ASA底层的网络接收函数来监听所有物理端口上的通信流量,并过滤出连接指令,无法通过网络探测的方式进行后门发现。此外,后门连接采用自定义网络协议,采用D-H算法协商密钥验证后才允许连接,通讯的过程也采用协商的密钥进行了加密,难以通过传统IDS或IPS检测攻击。因此,如果想准确的检测后门,必须按照后门通信协议构造网络数据包并获取真实后门的反馈才能够实现后门的探测。

4.ASA设备植入的后门的具备工程化和专业化。从泄露的文件目录看,后门研发组织对于网络基础设备拥有全平台的适配能力和模块化后门加载能力,整个后门攻击程序可以作为网络基础设施攻击框架,只需要挖掘到新的0DAY漏洞就可以方便的扩展沿用现有的攻击载荷,文件中包含多个针对网络设备的后门程序,这些程序拥有Rootkit能力,且具备加密和抗分析能力。尤其当攻击目标定向为不便重启和升级的基础网络设施时,其持久化后门即使升级后仍可能无法彻底清除,这对于安全防御和检测方是很大的挑战,针对网络设备固件完整性校验、网络设备内存完整性校验、以及固件的供应链安全将显得越发重要。

相关推荐