内容简介: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
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Learn Python the Hard Way
Zed A. Shaw / Addison-Wesley Professional / 2013-10-11 / USD 39.99
Master Python and become a programmer-even if you never thought you could! This breakthrough book and CD can help practically anyone get started in programming. It's called "The Hard Way," but it's re......一起来看看 《Learn Python the Hard Way》 这本书的介绍吧!
RGB转16进制工具
RGB HEX 互转工具
HTML 编码/解码
HTML 编码/解码