Gafgyt物联网僵尸网络家族分析
背景随着IOT(物联网)设备被越来越多的使用,互联网上针对IOT设备的攻击也在日益增加。相对于对传统终端安全性的重视,如各种杀软,终端检测,防火墙的使用,个人及企业用户对IOT设备的安全性重视仍然不够。加之IOT设备固件更新缓慢,被攻击后发现周期长的特性,使得攻击者可以以更低成本获得一台有更长控制权限的设备。这些被攻陷的IOT设备通常被用于发动DDoS攻击。著名僵尸网络家族mirai曾在2016年,利用数十万台IOT设备对域名解析商Dyn发起DDoS攻击,导致几乎整个美国东海岸的网络陷入瘫痪。Gafgyt是与Mirai类似的知名僵尸网络家族,本文将对其从多个角度进行详细分析。 简介Gafgyt(又称BASHLITE,Qbot,Lizkebab,LizardStresser)是一款基于IRC协议的物联网僵尸网络程序,主要用于发起DDoS攻击。它可以利用内置的用户名、密码字典进行telnet爆破和对IOT设备RCE(远程命令执行)漏洞利用进行自我传播。于2015年泄露源码并被上传至github,此后衍生出多个变种,次年对互联网上的IOT设备的总感染数达到100W。Gafgyt家族曾发起过峰值400Gbps的DDoS攻击。截至2019年底,Gafgyt家族仍是除Mirai家族外最大的活跃物联网僵尸网络家族。 样本来源本文分析的样本均来自于互联网。 攻击目标地域:不限 目标设备:IOT 目标行业:不限 In The Wild IP热力图 源码分析Client端注释 使用图形化的注释,将整个文件分为15个部分,分别为defines,includes,Config,Functions,Globals,FPRNG,utils,IP Utils,Telnet Scanner lel,UDP Flood,TCP Flood,JUNK Flood,Hold Flood,Send Email,IRC Main。 C2服务器列表 Globals,全局变量声明,包含爆破用的用户名/密码对 命令执行格式: !command arg PING命令,测试对方是否存活。 客户端 服务端 GETLOCALIP命令,使用getsockname获取本机ip并返回给服务器 SCANNER命令, 分为SCANNER ON/OFF两个命令,分别为开始/结束telnet扫描线程。整个扫描过程由state和complete两个标记位进行控制。telnet扫描共分为10步,下面对telnet扫描过程进行详细分析: 1 生成随机IP,并尝试对IP的23端口进行socket连接。如果连接成功,state置为1,进行下一步;否则state仍为0,重复当前步骤。 2 使用select函数判断上一步建立的socket连接是否可用,如果不可用将state置为0,返回第一步;如果可用继续用getsockopt函数获取socket的选项,获取成功state置为2,否则置为0。
3 尝试从socket返回的数据中查找”ogin”(推测为telnet的登陆标记login,为什么少了一位不清楚),如果能读取到state置为3
4 尝试发送用户名列表中的用户名和回车标记,如果发送成功state置为4
5 读取服务器端返回,如果上一步的用户名输入成功,服务器应该会进一步响应password并等待客户端输入密码,因此该步尝试从socket中查找“assword”标记,若找到state置为5,否则认为不需要密码可直接登录,state置为100;若找到的标记为“ncorrect”(推测为incorrect,用户名错误时服务器的响应内容),state置为0。
6 尝试发送密码和回车,发送成功标记state置为6
7 尝试查找服务器返回的字符串中是否由”ncorrect”标记,如果找到,state置为0,否则查找一系列登陆成功后的命令行标记(:>%$#\0),如果找到,state置为7
8 发送“sh/r/n”标记,尝试调用sh,发送成功state置为8,否则置为0
9 发送以下内容,成功state置为9 /bin/busybox;echo -e '\\147\\141\\171\\146\\147\\164'\r\n
10 检查返回值,打印结果:目标ip,登陆成功的用户名和密码 向指定邮件服务器发送请求,尝试向指定邮箱发送指定内容。在当前版本的源码中该方法被注释 TCP 泛洪攻击,向指定IP指定端口发送指定时间的随机字符串,使用命令 JUNK <ip> <port> <time> 发送的过程与telnet扫描类似,建立socket连接 判断连接是否可用 检查连接选项 最后生成1024长度的随机字符串并写入socket 随机字符串生成规则为任意大写字母 UDP命令,UDP泛洪攻击,向指定IP和端口发送指定时间长度的任意字符串,且具有源IP地址欺骗功能。使用命令: UDP <target> <port (0 for random)> <time> <netmask (32 for non spoofed)> <packet size (1 to 65500)> (time poll interval, default 10) 不开启源地址欺骗过程比较简单,建立连接,循环发送字符串 开启源地址欺骗需要先构造IP包,写入随机IP地址,并填充随机字符串,最后计算校验和并循环发送 TCP命令,TCP泛洪攻击,除TCP flags设置之外,其余与UDP基本一致。使用命令: TCP <target> <port (0 for random)> <time> <netmask (32 for non spoofed)> <flags (syn, ack, psh, rst, fin, all) comma seperated> (packet size, usually 0) (time poll interval, default 10) 攻击者可自定义tcp报文的flags位,可选项syn/rst/fin/ack/psh,且可任意选择一种或全部使用 HOLD命令,在指定时间内,持续尝试与指定IP和端口建立TCP连接,但是不发送任何数据 KILLATTK命令,通过Kill掉除主进程外的所有子进程来停止DoS攻击 LOLNOGTFO命令,C2通过IP地址判断,同一个肉鸡多次发送上线包时,即肉鸡多次执行恶意elf的情况,C2会下发该命令强制退出当前启动的进程。 流量分析PING/PONG指令 GETLOCALIP指令 SCANNER ON指令 JUNK指令 TCP伪造源IP,flags设置为all UDP伪造源IP,包长度设置为1000 HOLD命令 单条session DoS攻击小结攻击者在利用控制的僵尸主机发起DoS攻击时,出于隐藏攻击源IP的目的,会重新构造IP层报文以重设源IP;而TCP和UDP报文都是基于IP头的,当使用自建IP头时,TCP/UDP报文也需要重建。这种隐藏攻击源IP的方式常见于不需要建立三次握手的DoS攻击中,如TCP flood和UDP flood,需要建立三次握手的JUNK flood则会因为第二次握手包返回到伪造的IP而导致连接建立失败,无法通过TCP连接发送垃圾数据报文。而IP packet中的部分字段是有“上下文的“而非固定的,这就导致攻击者需要使用一些值去填充这些字段。 在Gafgyt家族客户端中,对IP头的重构部分源代码如下 可以看到IP头的id字段被填充为随机字符串。根据RFC定义,IP层包的头结构如下: 其中id应该是对应identification字段。操作系统中的IP构造方法会维持一个计数器,每产生一个IP报文该值会+1。攻击者在构造报文时无法读取上一个identification值,自然只能用随机或固定数值去填充。虽然IP协议是无连接协议,使得这个值不能作为序列号使用,但是identification值的自增特性决定了它一定程度上可以作为一种弱判断标记。 再来看TCP头的构造代码:
TCP头共有3个字段被填充为随机值,1个值被填充为0。TCP头结构如下:
代码中的source字段应该对应source port,可以忽略;seq字段对应sequence number,ack_seq字段对应acknowledgement number,这两者为TCP可靠传输的保证。sequence number为当前包中payload第一个字节的序号,acknowledgement number代表已接收数据的序号,这两者都是有状态的,如果能在性能允许的情况下维护一个TCP报文的序号表,那么使用这个表是可以进行这种类型的DoS防御的。即新来的报文既没有SYN标记,它的seq和ack序号又不能在序号表中找到对应项,那么该报文一定是可以直接丢弃的。 Window字段即滑动窗口值,该值用于接收端告诉发送端当前能够接收的最大数据字节数。该值会随接收方主机链路情况发生变化,不适用于DoS报文检测。 UDP包头中只有源端口被填充为随机值,在此不再分析。 主机特征开放端口,生成进程/子进程。 关联分析基于在一定时间内使用同一基础设施(如C2/ITW)的样本属于同一团伙的假设,对2019年捕获到的所有Gafgyt家族样本进行C2/ITW 信息提取并进行关联,关联结果如下: 其中红色点代表ITW地址,绿色点代表C2地址,每一条边代表所连接的两个点的地址曾出现在同一样本中(或从一个点对应地址下载的样本会以另一点对应地址为C2)。其中独立的点代表其ITW和ip为同一地址。 可以比较明显的看到关联超过5个点的类有三个,按照从下至上的顺序将其命名为家族1、家族2和家族3。 家族分析家族1家族1中包含1个C2地址和6个ITW地址。 从蜜罐获取样本的时间来看,该家族的活跃时间为2019年4月26日至今。4月26日第一次出现的样本,被存储在89.46.223.195服务器上,共涵盖9种架构,大多数为静态链接并剥离了调试信息,只有一个样本为静态编译未剥离调试信息。 从样本中方法调用情况来看,该样本并不完整,疑似攻击者正在对样本进行测试而未正式使用。与原始样本相比,该样本有如下变化: 增加了20+种控制命令,包含给客户端增加nickname,修改客户端内置C2地址,通讯流量加密以及远程下载文件并执行的方法,显著增强了样本功能(部分命令未实现) 添加自启动功能,避免设备重启后失去控制权
进行telnet扫描时使用如下payload,而原始样本仅进行弱口令扫描。 从脚本可以看出在进行传播时,脚本先通过wget获取样本托管服务器上的sh脚本保存到本地并重命名,再通过执行sh脚本进一步下载真正的恶意样本。Sh脚本会下载所有架构的样本并依次执行,以保证在不同架构的设备上都能够使对应的样本运行起来。 新增多种DoS攻击方式,且为可伪造源IP的DoS攻击编写了专门的包头构造方法
且字符串窗口中存在大量user-agent信息,疑似为实现CC攻击做准备: 增加对8种应用/设备的RCE漏洞扫描和利用 还有一段似乎是对某安全研究人员的嘲讽 攻击者于4月27日对样本进行了第一次更新,样本命名方式改为abe.+样本架构,仍然包括9种架构的样本,投递服务器为89.46.223.199。 对比发现内部仅有扫描Payload中的恶意脚本下载地址和编译器生成的部分内容发生改变,脚本下载地址由89.46.223.199修改为89.46.223.195。 此次更新后,89.46.223.195和89.46.223.199同事托管恶意样本且内置脚本下载链接均为对方IP。直到5月2日,新的恶意样本托管服务器89.46.223.180加入,托管样本与之前的两个IP托管的样本一致,样本内置扫描payload种的下载链接为89.46.223.195。 5月8日,新的恶意样本托管服务器89.46.223.81加入,且前述3个样本托管服务器均停止使用。89.46.223.81上托管的样本,内置扫描Payload中的downloader脚本为自身。 6月12日,新的样本托管服务器89.32.41.15上线,托管的样本仅有7种架构且均为剥离调试信息。对样本进行静态分析发现样本内容仍没有改动。内置扫描Payload中的恶意样本下载地址为89.46.223.81。 此后该家族停止恶意活动,直至10月22日重新开始恶意活动,此时恶意样本托管服务器ip为151.80.197.109,托管的样本仍然覆盖9种架构CPU,仍然只有64位MIPS架构样本未剥离调试信息。但是此时样本大小发生了明显变化,由之前的520KB变为720KB。 通过静态分析,本次样本更新主要新增了一下几种用于自我传播的RCE漏洞和用于CC攻击的User-Agent内容。新增漏洞payload如下: 小结 活跃时间线: 2019年4月26日,样本托管服务器89.46.223.195上线,样本内嵌下载ip:89.46.223.195 2019年4月27日,样本托管服务器89.46.223.199上线,样本内嵌下载ip: 89.46.223.195 2019年5月2日,样本托管服务器89.46.223.180上线,样本内嵌下载ip: 89.46.223.199 2019年5月8日,样本托管服务器89.46.223.81上线,样本内嵌下载ip: 89.46.223.81/89.46.223.195 2019年6月12日,样本托管服务器89.32.41.15上线,样本内嵌下载ip: 89.46.223.81/89.46.223.195 2019年10月22日,样本托管服务器151.80.197.109上线,样本内嵌下载ip: 151.80.197.109/89.46.223.81。样本新增漏洞利用Payload和User-Agent。 扩散手法:telnet弱口令扫描,RCE漏洞利用 目标地域:随机IP 目标设备:IOT 目标CPU架构:ARM,ARM(GNU/Linux),Intel 80386,MIPS64,MIPS-I,Motoroal 68020,PowerPC,Renesas SH,x86-64 样本编译情况:静态链接,stripped 漏洞列表:
IOC:
(涉及样本较多,不在此列出) 家族2家族2活跃支持的架构较少,在活跃时间范围内仅有4个样本。
如上表所示,样本均为静态编译且剥离了调试信息。 与原始样本相比,该家族样本主要变化如下: 通过将自身加入到系统初始化目录中实现自启动 入侵IOT设备成功后,通过修改配置文件、iptables禁用端口的方式关闭管理/控制端口,已以控制时间: 厂商一光猫:
厂商二光猫 利用10种RCE漏洞进行自我传播: 小结 活跃时间线: 2019年10月30日,样本托管服务器115.51.203.137上线,投递样本eda 2019年10月31日,样本托管服务器115.51.203.137新投递样本30a,624 2019年11月1日,样本托管服务器118.249.40.35和220.135.22.121上线,分别投递样本30a和eda; 2019年11月2日,样本托管服务器101.65.118.108和182.113.234.110上线,投递样本eda和b9d 2019年11月5日,样本托管服务器220.134.139.113上线,投递样本eda 2019年11月6日,样本托管服务器218.35.45.116上线,投递样本eda 2019年11月7日,样本托管服务器183.196.233.193上线,投递样本eda 2019年11月8日,样本托管服务器182.127.92.221和39.77.124.251上线,投递样本30a,624,eda 2019年11月10日,样本托管服务器42.225.182.239上线,投递样本30a和eda 2019年11月13日,样本托管服务器101.65.118.108上线,投递样本eda 2019年11月15日,样本托管服务器221.223.37.152和42.231.94.209上线,分别投递样本eda和30a 2019年11月16日,样本托管服务器114.240.90.197和221.223.37.152上线,分别投递样本30a、eda和30a、624 扩散手法:telnet弱口令扫描,RCE漏洞利用 目标地域:随机IP 目标设备:IOT 目标CPU架构:ARM, Intel 80386,MIPS-I 样本编译情况:静态链接,stripped IOC: 漏洞列表
IP列表
样本列表
用户名列表
密码列表
家族3家族3中包含1个C2和40个ITW IP。 该家族至少从2019年1月2日开始活动(只筛选了2019年以后的样本)至2019年9月28日。2019年样本第一出现是部署在31.214.157.71服务器上。
与家族1和2一致,该家族同样是先通过下载shell脚本再运行的方式下载真正的恶意二进制样本并运行,以适应不同架构设备环境。 这个shell脚本中使用了一个小技巧,即使用“||”符号来分隔cd directory命令。这样当/tmp目录不存在时,系统会提示“No such file or directory”,但仍会继续执行第二个cd directory命令。这样既能满足在不常用目录存储恶意样本不被发现的需求,又能在不常用目录不存在时使得恶意样本能正常保存下来。 与家族1和家族2相比,家族3的样本并没有刻意剥离调试信息;样本命名方式简单粗暴,直接采用架构简称作为样本名称:
对其中的x86架构样本进行简单静态分析,与原始代码区别如下: 首先对自身进程重命名为/usr/sbin/dropbear
调用table_init函数,初始化一系列加密后的数据 然后调用函数进行解密。从攻击者没有剥离调试信息看,进行加密的主要目的是防止直接从静态字符串中看到这些信息。
解密算法如下: 要获得解密后的信息有两种方式: 调试。使用ida pro远程调试样本,打开ida pro安装目录下的dbgsrv目录,根据样本架构选择linux_server64,与待调试样本一起放到一台linux主机的某一目录下,修改linux_server64的权限并运行,得到调试端口23946。简单分析代码逻辑,回到ida中在长度比较和结果返回两处位置下断
调试器选项中选择Remote Linux debugger,点击开始调试,输入linux主机IP和端口,断下来后观察异或操作时修改的位置,循环两次后发现程序对堆上的0x23e8050地址进行修改。取消第一个断点,运行发现字符串已经解密,内容为:
并不是想象中的恶意服务器地址信息。 当目标样本难以进行调试时,可以对解密逻辑进行分析,并使用Python代码实现逻辑完成解密。该样本进行了初始化和解密两个步骤,所以先需要分析初始化逻辑,将数据布置在内存中之后再进行解密。 初始化逻辑比较简单,直接将字符串部署在table列表的指定位置
解密函数的输入参数为待解密字符串在table种的索引,解密算法为从低到高依次取table_key的一位与加密字符串进行异或计算,异或后的结果继续与table_key取出的下一位进行异或,四次异或后即为解密结果。 使用Python实现以上逻辑: #coding:utf-8 key = ['\xBA', '\xFF', '\xDE', '\xDE'] s = '''6- ))E''' result = '' for index,c in enumerate(s): tmp = ord(c) for k in key: tmp = tmp ^ ord(k) result += (chr(tmp)) print(result) 依次对加密字符串进行解密,结果如下:
利用CVE-2017-17215远程命令执行漏洞进行传播
利用Realtek SDK - Miniigd UPnP SOAP远程命令执行漏洞进行传播
然后开始循环调用processCmd函数,监听来自服务端的信息,并进行对应处理。与原始样本相比,发生变化的命令变动如下: 新增“HTTP”命令,用于对目标地址发起CC攻击
新增“STD”命令,用于发起udp STD flood攻击
新增“CRASH”命令,用于发起RTCP flood攻击 新增“CRUSH”命令,用于发起TCP flood和STD flood。 新增“SMITE”命令,用于发起vse flood攻击。(类似TCP泛洪,建立TCP连接后发送随机字符串)
新增“CNC命令”,用于切换客户端连接的CNC端
然后直到2019年2月5日,攻击者在104.168.143.19上部署新样本。通过对比发现,仅有利用漏洞传播时payload中的下载链接发生变化
2019年2月20日,攻击者在104.168.169.89上部署新样本,样本功能仍未发生改变,利用漏洞传播时payload中的下载地址为31.214.157.71 2019年2月22日,攻击者在176.31.78.52上部署新样本,新增对4种RCE漏洞的利用。漏洞已包含在家族1中,在此不再详细分析。 2019年3月19日,攻击者在68.183.121.242上部署新样本,样本中增加了大量的User-Agent字符串
接下来一段时间内,攻击者一直在新的服务器上部署样本,但是样本功能基本未发生变化。知道2019年7月28日,攻击者在165.22.187.56上部署新样本,downloader脚本和样本命名方式均未改变,样本大小由141KB变化为245KB。但是经分析发现,攻击者只是在样本尾部添加了部分字符串,并未对样本结构产生影响,IDA也未解析这部分数据。 2019年8月7日,攻击者在185.244.25.75上部署新样本。样本命名方式变为样本md5作为样本名,样本内容未发生变化。 小结 活跃时间线: 2019年01月02日,样本托管服务器31.214.157.71上线,样本内嵌下载ip:31.214.157.71 2019年02月05日,样本托管服务器104.168.143.19上线,样本内嵌下载ip:104.168.143.19 2019年02月20日,样本托管服务器104.168.169.89上线,样本内嵌下载ip:31.214.157.71 2019年02月22日,样本托管服务器176.31.78.52上线,样本内嵌下载ip:176.31.78.52 2019年02月28日,样本托管服务器142.93.11.223上线,样本内嵌下载ip:142.93.11.223 2019年03月15日,样本托管服务器35.246.45.191上线,样本内嵌下载ip:35.246.45.191 2019年03月19日,样本托管服务器68.183.121.242上线,样本内嵌下载ip:68.183.121.242 2019年03月20日,样本托管服务器188.166.116.249上线,样本内嵌下载ip:188.166.116.249 2019年03月26日,样本托管服务器157.230.92.69上线,样本内嵌下载ip:157.230.92.69 2019年03月27日,样本托管服务器68.183.148.125上线,样本内嵌下载ip:68.183.148.125 2019年03月28日,样本托管服务器46.36.35.127上线,样本内嵌下载ip:46.36.35.127 2019年03月31日,样本托管服务器185.244.25.117上线,样本内嵌下载ip:185.244.25.117 2019年03月31日,样本托管服务器68.183.24.85上线,样本内嵌下载ip:68.183.24.85 2019年04月03日,样本托管服务器185.244.25.114上线,样本内嵌下载ip:185.244.25.114 2019年04月06日,样本托管服务器194.135.92.252上线,样本内嵌下载ip:194.135.92.252 2019年04月09日,样本托管服务器104.248.28.163上线,样本内嵌下载ip:104.248.28.163 2019年04月11日,样本托管服务器134.209.8.154上线,样本内嵌下载ip:134.209.8.154 2019年04月11日,样本托管服务器188.166.63.234上线,样本内嵌下载ip:188.166.63.234 2019年04月21日,样本托管服务器157.230.4.62上线,样本内嵌下载ip:157.230.4.62 2019年04月30日,样本托管服务器185.172.110.226上线,样本内嵌下载ip:185.172.110.226 2019年05月10日,样本托管服务器37.49.225.230上线,样本内嵌下载ip:37.49.225.230 2019年05月14日,样本托管服务器188.166.14.76上线,样本内嵌下载ip:188.166.14.76 2019年05月16日,样本托管服务器198.12.97.73上线,样本内嵌下载ip:198.12.97.73 2019年05月17日,样本托管服务器174.138.52.74上线,样本内嵌下载ip:174.138.52.74 2019年05月24日,样本托管服务器107.173.57.152上线,样本内嵌下载ip:107.173.57.152 2019年06月03日,样本托管服务器185.172.110.214上线,样本内嵌下载ip:185.172.110.214 2019年06月10日,样本托管服务器204.48.18.12上线,样本内嵌下载ip:204.48.18.12 2019年06月13日,样本托管服务器139.99.137.154上线,样本内嵌下载ip:139.99.137.154 2019年06月14日,样本托管服务器185.172.110.238上线,样本内嵌下载ip:185.181.11.144 2019年06月17日,样本托管服务器159.89.177.184上线,样本内嵌下载ip:159.89.177.184 2019年06月20日,样本托管服务器195.231.8.82上线,样本内嵌下载ip:195.231.8.82 2019年06月20日,样本托管服务器198.175.125.100上线,样本内嵌下载ip:104.248.167.251 2019年06月22日,样本托管服务器54.39.7.243上线,样本内嵌下载ip: 195.231.8.82 2019年07月02日,样本托管服务器198.199.76.237上线,样本内嵌下载ip:198.199.76.237 2019年07月07日,样本托管服务器178.128.245.57上线,样本内嵌下载ip:178.128.245.57 2019年07月09日,样本托管服务器134.209.80.188上线,样本内嵌下载ip:134.209.80.188 2019年07月26日,样本托管服务器167.114.115.119上线,样本内嵌下载ip:167.114.115.119 2019年07月28日,样本托管服务器165.22.187.56上线,样本内嵌下载ip:165.22.187.56 2019年08月06日,样本托管服务器185.244.25.75上线,样本内嵌下载ip:185.244.25.75 2019年09月28日,样本托管服务器174.128.226.101上线,样本内嵌下载ip:174.128.226.101 扩散手法:telnet弱口令扫描,RCE漏洞利用 目标地域:随机IP 目标设备:IOT 目标CPU架构:ARM,ARM(SYSV),Intel 80386,MIPS-I,Motoroal 68020,PowerPC,Renesas SH,x86-64,SPARC 样本编译情况:静态链接,not stripped IOC: 漏洞列表
IP列表
(涉及样本哈希较多,不在此列出) |
-
187****0268 2020-08-04 15:23:18 很详细!!