内容简介:CVE-2020-9054 PoC于上个月公开发布后立即被用来感染Zyxel NAS设备。Mirai新变体Mukashi暴力使用不同组合的默认凭据强制登录,将登录成功结果发送到命令和控制(C2)服务器。Zyxel NAS产品固件版本低于5.21容易受到此预身份验证命令注入漏洞的攻击。本文包括整个攻击图文分析和IoC。可执行文件weblogin.cgi在验证过程中未正确清除username参数。 攻击者可以使用单引号分号实现命令注入。 weblogin.cgi接受HTTP GET和POST请求,攻击者可以将恶
CVE-2020-9054 PoC于上个月公开发布后立即被用来感染Zyxel NAS设备。Mirai新变体Mukashi暴力使用不同组合的默认凭据强制登录,将登录成功结果发送到命令和控制(C2)服务器。Zyxel NAS产品固件版本低于5.21容易受到此预身份验证命令注入漏洞的攻击。本文包括整个攻击图文分析和IoC。
漏洞分析
可执行文件weblogin.cgi在验证过程中未正确清除username参数。 攻击者可以使用单引号分号实现命令注入。 weblogin.cgi接受HTTP GET和POST请求,攻击者可以将恶意有效负载嵌入HTTP请求并进行代码执行。
在野利用
第一次事件发生在2020年3月12日19:07,如下图1和2所示,攻击者试图将 Shell 脚本下载到tmp目录,执行脚本并删除设备上的攻击痕迹。
执行后脚本下载不同体系结构的Mirai bot,运行下载的二进制文件,然后删除。
新Mirai变体:Mukashi
Mukashi是一个自动化程序,它扫描随机主机的TCP端口23,使用不同的默认凭据组合强行强登录,并向其C2服务器报告成功的登录。像其他Mirai变体一样,Mukashi也能够接收C2命令并发起DDoS攻击。
执行后,Mukashi将显示“Protecting your device from further infections”。然后该恶意软件将其进程名改为dvrhelper,这表明Mukashi可能会继承其前身的某些特征。
在执行操作之前,Mukashi绑定到TCP端口23448,确保在受感染的系统上仅有一个实例运行。恶意软件在初始化期间会即时解码字符串。如下表所示,这些解码后的字符串包括凭据以及C2命令。Mukashi使用自定义解密函数对这些命令和凭据进行加密。附录中提供了解密脚本。
当恶意软件执行凭据暴力攻击时,Mukashi将使用默认密码,例如t0talc0ntr0l4!和taZz@23495859,以及在扫描阶段前已解码的凭据。 图3显示了Mukashi扫描随机主机时捕获的流量,图4显示了恶意软件暴力身份验证尝试。
成功登录后,Mukashi将有效凭据报告给C2服务器45.84.196.75。该消息具有以下格式<host ip addr>:23 <username>:<password>。 下图显示了此类消息的示例。
恶意软件启动并初始化,将信标发送回C2服务器45.84.196.75,监听端口4864,通知其C2服务器已准备好执行命令。 信标示例如图6中显示,具有以下格式:<名称>.<输入参数>.<name>, 如果成功创建了套接字,则<name>为root,否则为默认值。 <input arguments>子字符串是执行二进制文件时的参数。 如果未提供输入参数,则字符串为“无”。
Mukashi的DDoS功能与Mirai及其变体的DDoS攻击机制(例如UDP,TCP,UDP绕过和TCP绕过)相同。 Mukashi包含dvrhelper变体的某些功能,还具有抵抗DDoS防御功能。 下表显示了Mukashi支持的C2命令。
Attack_parsing函数负责处理Mukashi从C2服务器接收的命令。除了命令类型和目标地址之外还包括其他相关信息,如SYN标志,ACK标志,URG标志,PSH标志,Rst标志,时间字段,目标端口,数据包长度等。如果目标端口不可用,Mukashi将选择一个随机端口。 如果未指定数据包的长度,则Mukashi将使用默认值1458。
下图显示了x86版本与arm7版本的区别。
建议用户更新固件,使用复杂登录密码。
IoCs
File (Sha256)
8c0c4d8d727bff5e03f6b2aae125d3e3607948d9dff578b18be0add2fff3411c (arm.bot) 5f918c2b5316c52cbb564269b116ce63935691ee6debe06ce1693ad29dbb5740 (arm5.bot) 8fa54788885679e4677296fca4fe4e949ca85783a057750c658543645fb8682f (arm6.bot) 90392af3fdc7af968cc6d054fc1a99c5156de5b1834d6432076c40d548283c22 (arm7.bot) 675f4af00520905e31ff96ecef2d4dc77166481f584da89a39a798ea18ae2144 (mips.bot) 46228151b547c905de9772211ce559592498e0c8894379f14adb1ef6c44f8933 (mpsl.bot) 753914aa3549e52af2627992731ca18e702f652391c161483f532173daeb0bbd (sh4.bot) ce793ddec5410c5104d0ea23809a40dd222473e3d984a1e531e735aebf46c9dc (x86.bot) a059e47b4c76b6bbd70ca4db6b454fd9aa19e5a0487c8032fe54fa707b0f926d (zi)
Network
45[.]84[.]196[.]75:34834 (Report Successful Login Attempt) 45[.]84[.]196[.]75:4864 (Command and Control) 0[.]0[.]0[.]0:23448 (Singleton)
IDApython 6.x-7.3 Script
import ida_kernwin from idc import * from idautils import * from idaapi import * def decode_str(encoded_str): if len(encoded_str) == 0: return “” buf = list(encoded_str) result = ” buf[0] = chr(ord(buf[0]) – 2) slen = len(encoded_str) v1 = slen / 2; if v1 > 0: i = v1 while True: if i >= slen: break; buf[i] = chr(ord(buf[i]) – 1); i += 1 v2 = slen / 4; if v2 > 0: j = v2 while True: if j >= slen: break; buf[j] = chr(ord(buf[j]) – 1) j += 1 for k in xrange(0, slen): buf[k] = chr(ord(buf[k]) – 1) v3 = 0 if slen > 24: if slen > 99: v3 = slen / 5 – 3; else: v3 = slen / 5 – 1; else: v3 = slen / 5; l = v3 while True: if l >= slen: break buf[l]= chr(0); l += 1 result = “”.join(buf) return result def main(): for addr in XrefsTo(0x080482A0, flags=0): print(“[*] addr.frm {0}”.format(hex(addr.frm))) prev_addr = PrevHead(addr.frm) encoded_str = “” if GetMnem(prev_addr) == “push”: str_addr = GetOperandValue(prev_addr, 0) elif GetMnem(prev_addr) == “mov”: str_addr = GetOperandValue(prev_addr, 1) print(“\tstr_addr: {0}”.format(hex(str_addr))) encoded_str = GetString(str_addr) print(“\tencoded_str: {0}”.format(encoded_str)) decoded_str = decode_str(encoded_str) print(“\tdecoded_str: {0}”.format(decoded_str)) if __name__ == ‘__main__’: main()
IDApython 7.4 Script
def decrypt_string(enc_str): strlen = len(enc_str)str = chr(ord(enc_str[0])-2) + enc_str[1:]v1 = strlen/2 if v1>0: str = str[0:v1] + ”.join([chr(ord(x)-1) for x in str[v1:]]) v2 = strlen/4 if v2>0: str = str[0:v2] + ”.join([chr(ord(x)-1) for x in str[v2:]]) str = ”.join([chr(ord(x)-1) for x in str]) if strlen>24: if strlen>99: v9 = strlen/5 – 3 else: v9 = strlen/5 – 1 else: v9 = strlen/5 str = str[:v9] + chr(0) + str[v9+1:] return str def main(): strrefs = [] for addr in XrefsTo(0x080482a0, flags=0): prev_ins = prev_head(addr.frm) ref = get_operand_value(prev_ins, 1) if ref>0: strrefs.append(ref) for ref in strrefs: enc_str = get_strlit_contents(ref) print “Encrypted string: %s” %enc_str dec_str = decrypt_string(enc_str) print “Decrypted string: %s” %dec_str if __name__ == ‘__main__’: main()
*参考来源: unit42 ,由Kriston编译,转载请注明来自FreeBuf.COM
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 更难以检测的逃避机制——Gootkit银行木马新变体分析
- PoS变体图鉴
- 谈谈二分搜索及其变体
- 目标检测之非极大值抑制(NMS)各种变体
- Intel 披露新型 Spectre 漏洞变体:Lazy FP 状态还原
- Crystal 语言发布 0.25.0 版本,静态类型的 Ruby 变体
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
国际大学生程序设计竞赛例题解
郭嵩山 / 电子工业出版社 / 2007-7 / 32.00元
《国际大学生程序设计竞赛例题解3:图论、动态规划算法、综合题专集》以图论、动态规划算法、综合题的形式介绍了ACM国际大学生程序设计竞赛(ACM/ICPC)中所用到的典型算法,并结合例题,对如何灵活地运用这些算法进行比较详细分析和深入浅出的讲解。《国际大学生程序设计竞赛例题解3:图论、动态规划算法、综合题专集》以精讲多练为教学宗旨,并在每一个专题论述后用一章的篇幅选出一批有代表性的竞赛例题,对每道例......一起来看看 《国际大学生程序设计竞赛例题解》 这本书的介绍吧!
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
XML 在线格式化
在线 XML 格式化压缩工具