А АWednesday 28 October 2020

Python и Scapy - сладкая парочка #1.

Всем привет.

Повторение - мать учения.  Так уж получилось что пришлось писать макет лабораторной работы для студентов в которой участвуют Python и Scapy. Поэтому часть материала будет для вас знакома. 

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

На момент написания этой заметки Scapy 2.3.3 поддерживает Python 2.7.17. Хотя и были предприняты попытки для поддержки Python 3, они всё ещё являются прототипами, поэтому мы будем применять Python 2.7 для своего случая. Основная идея в том, что Scapy 3 будет только для Python 3 и не будет обратной совместимости со Scapy 2.x. Как говорится - не впервой.

Итак, ставим саму Scapy:

admin1@admin1-VirtualBox:~$ sudo apt-get update

admin1@admin1-VirtualBox:~$ sudo apt-get install git

admin1@admin1-VirtualBox:~$ git clone https://github.com/secdev/scapy

admin1@admin1-VirtualBox:~$ cd scapy/

admin1@admin1-VirtualBox:~/scapy$ sudo python setup.py install


Быстрая проверка для того чтобы убедиться, что все пакеты установлены правильно:

admin1@admin1-VirtualBox:~/scapy$ python

Python 2.7.17 (default, Mar 30 2020)

[GCC 7.5.0] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> from scapy.all import *

Пустой ответ значит что все ок.


В своём первом примере мы поработаем с пакетом ICMP (Internet Control Message Protocol, Межсетевого протокола управляющих сообщений) на своём клиенте и отправим его на наш сервер. На стороне самого сервера мы применим tcpdump в фильтре хоста для просмотра входящего пакета:

## Сторона клиента

admin1@admin1-VirtualBox:~/scapy$ sudo scapy

<пропуск>

Welcome to Scapy (2.3.3)

>>> send(IP(dst="10.0.0.14")/ICMP())

.

Sent 1 packets.

>>>

## Сторона сервера

webfront@server:~$ sudo tcpdump -i eth1 host 10.0.0.10

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes

10:45:11.879192 IP 10.0.0.10 > 10.0.0.14: ICMP echo request, id 0, seq 0, length 8

10:45:11.879192 IP 10.0.0.14 > 10.0.0.10: ICMP echo reply, id 0, seq 0, length 8

Как вы можете видеть, обработать вручную пакет очень просто. Scapy позволяет вам построить сам уровень пакета при помощи символа слэша (/) в качестве необходимого разделителя. Имеющаяся функция send работает на слое 3 уровня, который заботится для вас о маршрутизации и уровне 2. Также имеется альтернатива sendp(), которая функционирует на 2 уровне, что означает, что вам потребуется определять сам интерфейс и протокол канального уровня.

Давайте рассмотрим перехват самого возвращаемого пакета с применением имеющейся функции отправки запроса (sr, send-request). Мы применяем особый вариант с названием sr1 этой функции, который возвращает только один пакет из отправляемого ответа на заданный пакет:

>>> p = sr1(IP(dst="10.0.0.14")/ICMP())

>>> p

<IP version=4L ihl=5L tos=0x0 len=28 id=26713 flags= frag=0L ttl=62 proto=icmp chksum=0x71 src=10.0.0.14 dst=10.0.0.10 options=[] |<ICMPtype=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |>>

Один момент, которые следует отметить, состоит в том, что сама функция sr возвращает кортеж, 

содержащий ответный и безответный списки:

>>> p = sr(IP(dst="10.0.0.14")/ICMP())

>>> type(p)

<type 'tuple'>

## распаковка

>>> ans,unans = sr(IP(dst="10.0.0.14")/ICMP())

>>> type(ans)

<class 'scapy.plist.SndRcvList'>

>>> type(unans)

<class 'scapy.plist.PacketList'>

Если вам необходимо только взглянуть на сам список пакетов ответа, мы можем просмотреть его в другом кортеже, содержащем те пакеты, которые мы должны отправить помимо самого возвращаемого пакета:

>>> for i in ans:

...     print(type(i))

...

<type 'tuple'>

>>> for i in ans:

...     print i

...

(<IP frag=0 proto=icmp dst=10.0.0.14 |<ICMP |>>, <IP version=4L ihl=5L tos=0x0 len=28 id=27062 flags= frag=0L ttl=62 proto=icmp chksum=0xff13 src=10.0.0.14 dst=10.0.0.10 options=[] |<ICMP type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |>>)

Scapy также предоставляет конструкцию уровня 7 помимо всего прочего, например, запрос к DNS. В приводимом ниже примере мы опрашиваем открытый сервер DNS для разрешения www.google.com:

>>> p = sr1(IP(dst="8.8.8.8")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.google.com")))

>>> p

<IP version=4L ihl=5L tos=0x0 len=76 id=21743 flags= frag=0L ttl=128 proto=udp chksum=0x27fa src=8.8.8.8 dst=172.16.1.152 options=[] |<UDP sport=domain dport=domain len=56 chksum=0xc077 |<DNS id=0 qr=1L opcode=QUERY aa=0L tc=0L rd=1L ra=1L z=0L ad=0L cd=0L rcode=ok qdcount=1 ancount=1 nscount=0 arcount=0 qd=<DNSQR qname='www.google.com.' qtype=A qclass=IN |> an=<DNSRR rrname='www.google.com.' type=A rclass=IN ttl=299 rdata='172.217.3.164' |> ns=None ar=None |>>>

>>>

Снифинг.

Scapy можно также применять для простого захвата пакетов:

>>> a = sniff(filter="icmp and host 172.217.3.164", count=5)

>>> a.show()

0000 Ether / IP / TCP 192.168.225.146:ssh > 192.168.225.1:50862 PA / Raw

0001 Ether / IP / ICMP 192.168.225.146 > 172.217.3.164 echo-request 0 / Raw

0002 Ether / IP / ICMP 172.217.3.164 > 192.168.225.146 echo-reply 0 / Raw

0003 Ether / IP / ICMP 192.168.225.146 > 172.217.3.164 echo-request 0 / Raw

0004 Ether / IP / ICMP 172.217.3.164 > 192.168.225.146 echo-reply 0 / Raw

>>>

Мы можем взглянуть на полученные пакеты более подробно:

>>> for i in a:

... print i.show()

...

<пропуск>

###[ Ethernet ]###

 dst= <>

 src= <>

 type= 0x800

###[ IP ]###

 version= 4L

 ihl= 5L

 tos= 0x0

 len= 84

 id= 15714

 flags= DF

 frag= 0L

 ttl= 64

 proto= icmp

 chksum= 0xaa8e

 src= 192.168.225.146

 dst= 172.217.3.164

 options

###[ ICMP ]###

 type= echo-request

 code= 0

 chksum= 0xe1cf

 id= 0xaa67

 seq= 0x1

###[ Raw ]###

 load= 'xd6xbfxb1Xx00x00x00x00x1axdcnx00x00x00x00x00x10x11x12x13x14x15x16x17x18x19x1ax1bx1cx1dx1ex1f !"#$%&'()*+,-./01234567'

None

В второй части посмотрим как мы можем применять Scapy для общей проверки безопасности.

Успехов.

No comments:

Post a Comment

А что вы думаете по этому поводу?

Версия на печать

Популярное