Scapy kasutamine

Allikas: Imre kasutab arvutit

Sissejuhatus

Scapy http://www.secdev.org/projects/scapy/ abil saab töötada pakettidega. Tarkvarale on tehtud Python keeles ja sellele on iseloomulik, et saab nö programmeerimise võtteid kasutades nt koostada sobiva sisuga paketi ja saata võrku; seejärel saab käsitleda sarnaselt vastuseks tulnud paketti. Scapy sisaldab mitmeid lisasid, nt saab lasta esitada graafiliselt traceroute tulemuse.

Tarkvara paigaldamine

Tarkvara paigaldamiseks sobib paigaldada nt Debian Squeeze all pakett python-scapy

# apt-get install python-scapy

Tarkvara kasutamine interaktiivselt Python promptist

Interaktiivselt käivitamiseks tuleb öelda

Pakettide moodustamine

TODO

Pakettide saatmine

Syn paketi väljasaatmiseks, seejuures saab määrata ka src aadressi

>>> sr1(IP(dst="10.80.123.154", src="10.204.62.116")/TCP(dport=80,flags="S"))

UDP DNS päringuga paketi väljasaatmiseks

>>> sr1(IP(dst="10.80.103.200", src="10.204.62.116")/UDP()/DNS(rd=1,qd=DNSQR(qname="loomaaed.tartu.ee")))
  • ICMP paketi saatmine
>>> send(IP(dst="192.168.10.123")/ICMP())
  • etteantud subnetti kuuluva juhusliku src aadressiga pakettide saatmine
>>> send(IP(src=RandIP("192.168.10.0/24"), dst="10.192.0.53")/TCP(dport=80,flags="S"), loop=1)

Pakettide saatmine ja vastuste töötlemine

TODO

Võrguliikluse jälgimine

TODO

Võrgu joonistamine

# scapy
...
Welcome to Scapy (2.1.0)
>>> res,unans = traceroute(["www.eesti.ee", "www.eenet.ee"],dport=[80,443],maxttl=20,retry=-2)
..
>>> res.graph()

Tulemusena esitatakse sarnane pilt

Scapy-1.gif

Scapy teekide kasutamine Python skriptist

HTTP võrguliiklusest GET päringute logimine

Skript logib HTTP liiklusest GET päringuid, versioon 1

# cat scapy_http.py
#!/usr/bin/python
import re
from scapy.all import *
from time import localtime, strftime

def http_monitor_callback(pkt):
  tcp_payload=str(pkt[TCP].payload)

  if re.search('^GET /', tcp_payload):
    return strftime("%a, %d %b %Y %X", localtime()) + ' ' + tcp_payload.split('\r\n')[1] + ' '\
      +  tcp_payload.split('\r\n')[0][:100]

sniff(prn=http_monitor_callback, filter="tcp port 80 and not host 192.168.252.222", store=0)

kus

  • esmalt imporditakse vajalikud teegid
  • kirjeldatakse funktsioon http_monitor_callback(), mille argumendiks on ip pakett
  • tcp_payload muutuja väärtustatakse IP paketis sisalduva TCP osa sisuga, mis on viidud string kujule (see on mitmerealine string tavaliselt)
  • edasi töötatakse 'GET /' sõne sisaldavate pakettidega
  • mitmerealine sisu splititakse \r\n kohalt saades eristada üksteisest HTTP päised
  • tagastatakse aeg ning kaks esimest rida: loendi teisel positsioonil on tihtipeale Host: kirje ja esimesel positsioonil GET päring; [:100] kasutab sõne sadat esimest tähte
  • sniff funktsioon kirjeldab filtri, asjaolu, et pakette mälus ei säilitata ja kutsub välja http_monitor_callback funktsiooni

Töötamas paistab skript sedasi

# ./scapy_http.py
Host: ftp.aso.ee GET / HTTP/1.1
Host: ftp.aso.ee GET /icons/blank.gif HTTP/1.1
Host: ftp.aso.ee GET /icons/hand.right.gif HTTP/1.1
Host: ftp.aso.ee GET /icons/folder.gif HTTP/1.1
Host: ftp.aso.ee GET /icons/text.gif HTTP/1.1
...

Esitatud skriptil on mitmed olulised puudused

  • eeldatakse, et HTTP päringus on kohe GET päringu järel Host: päis (vahel nii on, tihtipeale ei ole)
  • et saa mugavalt vajadusel muid HTTP päised esitada

Skript logib HTTP liiklusest GET päringuid, versioon 2

#!/usr/local/bin/python
import re
from scapy.all import *
from time import localtime, strftime

def http_monitor_callback(pkt):
    tcp_payload=str(pkt[TCP].payload)
    if re.search("^GET /", tcp_payload):
      vaartused={}
      j = 0
      for i in tcp_payload.split('\r\n'):
        if j == 0:
          get_paring = i.rstrip()
        if j > 0:
          i = i.rstrip()
          andmed = i.split(': ')

          try:
            vaartused[andmed[0]] = andmed[1]
          except:
            pass
        j = j + 1

      try:
        if vaartused['Host']:
          return strftime("%a, %d %b %Y %X", localtime()) + ' ' + pkt[IP].src + ' -> '\
            + pkt[IP].dst + ' ' + vaartused['Host'] + ' ' + get_paring[:60]
      except:
        return tcp_payload

sniff(prn=http_monitor_callback, filter="tcp port 80 and not host 192.168.252.222", store=0)

TODO

  • src ip aadressi asemel näidata AS numbrit
  • ühe tcp ühenduse peal uurida ainult niipalju pakette, kui GET päringu leidmiseks on tarvis
  • kasutada nn sample'imist, nt esitatakse iga kümnes GET päring

DNS võrguliiklusest päringute logimine

TODO

Scapy ja IPv6

TODO

Kasulikud lisamaterjalid