lunes, 20 de agosto de 2012

Escrebendo un sniffer en [python] co scapy

Scapy é unha librería de python que permite fozar coa rede dunha forma incriblemente sinxela, dende enviar pacotes feitos a man para interromper unha conexión allea ou para experimentar cos protocolos a ler todo o que pasa pola rede, hoxe faremos iso, e dicir un sniffer.

A verba sniffer deriva do inglés `sniff` "olfatexar", xa que o programa "ule" todo o que pasa pola rede, pero non nos adiantemos os acontecementos...

Como instalar Scapy


Nun sistema Gnu/Linux a instalación da librería non ten máis complicación que instalar o pacote correspondente, nas distribucións baseadas en Debian: python-scapy
Se por exemplo escrebemos no terminal
sudo apt-get install python-scapy
o sistema descargará e instalará o paquete automáticamente.

Botando o cadelo a cazar

Para poñer o scapy a ler o que pasa pola rede so fai falla importa-lo módulo:
from scapy.all import *

E darlle a orde de facelo:
sniff(filter=<filtro>, prn=<función_manexadora>)

Nota: é posible que diga algo coma "WARNING: No route found for IPv6 destination :: (no default route?)", isto é normal e so ven dicindo que non atopa unha rede co protocolo IPv6, non ten maior repercusión.

Iso si, é necesario recordar que para isto fan falla permisos de superusuario, así que cando se execute haberá que telo en conta e, por exemplo, por un `sudo` antes do comando.

Se vos fixades, quedan duas cousas que definir (non son completamente necesarias, pero se queremos facer algo, pois... si), a primeira é un filtro, este escollerá os pacotes que se lerán, podemos por exemplo ignorar os que corresponden a un porto, orixe, destino ou protocolo de rede que non nos interesa. A segunda é una función que receberá o pacote e (previsiblemente) fará o que queiramos que faga con el.

Os filtros


Os filtros empregados por Scapy son os filtros propios do `tcpdump`, un programa sniffer que xerou a librería do mesmo propósito `libpcap`, que a súa vez forma parte da base de `scapy`.

Un exemplo de filtro sería, "tcp" para só ler as conexións feitas a través de TCP, ou "port 80" para as conexións na que o orixe ou destiño sea o porto 80.

Este tema é bastante extenso de por si, pero baste saber que os filtros podense compoñer utilizando "not" coma operador "negación", "&&" coma operador "e lóxico" e "||" como operador "ou lóxico".

Pódese encontrar máis por exemplo en [ http://www.alexonlinux.com/tcpdump-for-dummies#packet_filtering ] ou facendo unha busca [ https://duckduckgo.com/html/?q=tcpdump+filters ].


A función de callback


A función non ten gran misterio, recebe coma parámetro o pacote, así que para ir pechando veremos como facer un sniffer para contrasinais de FTP, así vemos a función traballar con todo o conxunto.

#!/usr/bin/env python
# coding: utf-8

from scapy.all import sniff, TCP

# Os servidores FTP funcionan sobre TCP e (normalmente) no porto 21.
filtro = "tcp && port 21"

# Lee un pacote e avisa se atopa algo que 
# poida ser un usuario ou contrasinal
def manexadora(pacote):
    # Lemos os dados que envía (o payload en inglés)
    dados = pacote[TCP].payload

    # Senon ten nada, voltamos
    if dados is None:
        return None

    # Se o ten convertémolo nunha cadea de caracteres
    else:
        dados = str(dados)
        

    # No FTP, cando alguen se autentica primeiro manda
    # unha cadea con 'USER ' e o nome de usuario
    # e despois 'PASS ' e o contrasinal, imos buscar esas
    # referencias.
    if (dados.startswith("USER ") or
        dados.startswith("PASS ")):

        # Se a función manexadora devolve algo, o sniffer
        # mandao pola pantalla.
        # Recordando elimiñar os saltos de liña ou espacios
        # o final da cadea
        return dados.strip()

# Para rematar, lanzamo-lo sniffer
sniff(filter=filtro,
      prn=manexadora)


E iso é todo, espero que resultara interesante.

Saúdos

No hay comentarios:

Publicar un comentario