SniffJoke è il nome di un software rilasciato il 20/2/2007 che implementa tecniche di sniffing evasion note. Nonostante la loro utilità non erano mai state implementate sotto forma di software libero. Il software è previsto per Linux 2.6 e fa uso del framework netfilter+ulogd.

La finalità di SniffJoke è di rendere le connessioni TCP di un certo computer in rete immuni agli sniffer o altri strumenti che effettuano l’analisi passiva del traffico.

Dal punto di vista scientifico non è stato più detto nulla di nuovo dopo il 1998 con questo paper: Insertion, Evasion, and Denial of Service: Eluding Network Intrusion Detection Nel 2006, alla BlackHats conference, è stato rispolverato l’argomento, con il titolo Total IDS evasion

E’ l’implementazione che è sempre mancata. La difficoltà stava, probabilmente, nelle modalità di injection.

Normalmente l’injection basata su socket raw presupponeva la creazione da 0 dei pacchetti. Un esempio di creazione di pacchetti raw la si ha con il software hping.

Per effettuare sniffer/IDS evasion non è sufficente forgiare i pacchetti, ma è necessario che essi siano apparentemente appartenenti ad una connessione stabilita. Questo è affrontabile in due modi:

  • inviarli in modo parallelo alla reale connessione, oppure
  • sostituirsi a chi invia, controllando il traffico.

L’injection in parallelo la si fa analizzando il traffico che passa sulla propria interfaccia di rete e riciclando i pacchetti letti apportando parziali modifiche. Ad esempio, con una sessione telnet da

192.168.1.1:1024->192.168.1.2:23

  1. leggerò il pacchetto inviato dalla mia macchina (192.168.1.1)
  2. modificherò alcuni parametri e, avendo l’accortezza di lasciare gli indirizzi e le porte inalterate,
  3. potrò rinviare un pacchetto che, a destinazione, verrà associato alla connessione già stabilita.

Quanto detto si può fare con le comode librerie pcap o con ulogd (tramite il netlink device).

Più efficientemente si risolve prendendo completamente il controllo della sessione (gestita dal kernel) in userspace; per far questo occorre mettersi in mezzo tra il proprio kernel e l’invio dei pacchetti. Le tre tecniche finora sviluppate sono state:

  • innova, che nonostante il tempo dedicatogli non l’ho voluto rispolverare
  • packet purgatory, che usa un sistema di man in the middle con un IP fittizzio sulla propria interfaccia di rete
  • ettercap-ng, con l’uso di plugin appositi

L’implementazione è stata molto più comoda sotto forma di plugin per ulogd. Nonostante questa scelta impedisca l’implementazione di un paio di tecniche (ostanzialmente, quelle basate sulla frammentazione), la maggior parte degli hack funzionano inviando dei pacchetti in modo simmetrico alla connessione.

Spiegando grossolanamente la tecnologia sottostante: uno sniffer è uno strumento intermedio e passivo tra due macchine che comunicano, legge il traffico che transita in rete e ne effettua una ricostruzione (da pacchetti a sessioni). Ogni volta che riceve un pacchetto cerca la sessione al quale corrisponde e lo accoda. Oltre che di semplici dati, il pacchetto e’ composto da codici di messaggio e verifica (flag, sequence number, ack) grazie i quali verifica quali sono le sessioni nuove e quali quelle terminate.

Uno stack TCP/IP di un sistema operativo è un’implementazione davvero complessa. Uno sniffer è a sua volta complesso, ma l’obiettivo principale non è supportare le feature uscite sei mesi prima. Gli obiettivi perseguiti nella realizzazione di uno sniffer sono:

  • avere buone performance
  • ricostruire sessioni
  • analizzare le sessioni, e
  • salvarle

La differenza degli scopi tra stack TCP/IP e sniffer già indica uno spiraglio d’attacco: il fatto che uno sniffer sia più semplice, significa che usando al massimo le opzioni IP e TCP potrebbe avere difficoltà nella ricostruzione in sessioni? Plausibile.

Facendo le dovute assunzioni, si potrebbe pensare che uno sniffer non verifichi il checksum dei pacchetti, quindi il traffico verrebbe letto dallo sniffer ed accettato (dopo alcune verifiche sommarie), mentre il destinatario che effettua la verifica da RFC lo scarterebbe.

Nonostante l’esempio del checksum errato possa sembrare banale, perchè qualunque sniffer può implementare rapidamenta una verifica di quel tipo, ho:

  • avviato sniffjoke ed un client IRC
  • sniffato una sessione IRC con tcpdump (tcpdump -s 0 -ni eth0 -w output.pcap)
  • analizzato il dump con ethereal:

ethereal-follow-tcp-session.jpg

Usando l’opzione “follow tcp stream” si vedono:

  • l’accesso iniziale
  • la registrazione al server IRC
  • la conversazione che sembra finita (se ci si limita ad osservare la ricostruzione automtica)

Con un’analisi manuale si vede che la sessione discriminata dalla tupla 10.0.0.235:2195+62.211.69.9:6667 è proseguita per un po’ fino alla sua chiusura applicativa:

ethereal-real-irc-exit.jpg

E, nonostante ethereal non abbia necessità di alte performance e sia il riferimento per tutti tra i sistemi di network analysis, non è stato in grado di proseguire con la ricostruzione incappando in questi pacchetti:

ethereal-bad-cksum.jpg

L’hack del checksum errato è il più banale tra quelli indicati (per chi vuole approfondire, leggendo il funzionamento degli sniffer che effettuano session tracking vedrà che altri attacchi sono molto più difficili da evitare). Ad esempio la morte prematura di un pacchetto per expire del TTL: si manda un pacchetto del tutto legittimo con un TTL tale per cui il pacchetto scada un hop prima che raggiunga destinazione, lo sniffer interpreterà la chiusura ed il destinatario no.

Importante era inquadrare il concetto di attacco: fare in modo che uno sniffer consideri un pacchetto che il destinatario scarterà (o viceversa), in questo modo le sessioni tracciate da sniffer ed host saranno desincronizzate, differenti, fasulle.

L’uso più intuitivo di questa desincronizzazione consiste nell’inviare un pacchetto di chiusura in modo che lo sniffer lo accetti e l’host remoto no, così da far rimuovere la propria connessione da quelle tracciate e proseguire in libertà la propria trasmissione. Si può anche iniettare traffico falso in modo da mandare fuori sequenza lo sniffer.

Diventano rilevanti ora le assunzioni che vengono fatte, a supporto della tesi che gli sniffer sono vulnerabili a questi attacchi, quando non tutti gli sniffer sono di pubblico dominio. Dall’introduzione del README:

SNIFFJOKE per funzionare si basa su una caratteristica intrinseca degli sniffer, ovvero che se devono leggere giga e giga di traffico, ricostruire le connessioni ed analizzarle, devono fare delle assunzioni a priori (es: mi fido del checksum, mi fido dell’integrità dell’header TCP, mi fido che ogni sessioni inizi con SYN)

Vengono fatte delle assunzioni perchè gli algoritmi che ricostruiscono migliaia di sessioni al secondo devono essere necessariamente semplici, incomplete rispetto ad uno stack TCP/IP.

I tre motivi che portano a questa semplificazione sono:

  1. Deve supportare gli stack TCP/IP, essi sono definiti dalle RFC, ma le RFC definiscono come devono comportarsi gli host ai due capi della connessione, come deve comportarsi un sistema intermedio non è definito ne previsto
  2. Avendo visibilà sul traffico di un provider (locale, nazionale ?) la quantità di anomalie di rete sarà di gran lunga superiore alla quantità di anomalie che un tecnico di rete è abituato a vedere. Prevedere ogni malfunzionamento e discriminarlo in modo granulare richiederebbe una quantità di verifiche forse eccessivo per strumenti che devono reggere alte performance. Questo implica una granularità minore ed una più facile tendenza a scartare le anomalie, piuttosto che a gestirle
  3. Quando c’è un progetto che deve essere venduto, lo sviluppo viene incentrato su quello che viene visto, sulla bellezza della feature di ricerca ad analisi, di riconoscimento della signature e di similitudine, ma che poi i pacchetti non siano con precisione tutti quello non lo sa nessuno. Cercare di spiegarlo ai reparti superiori dell’azienda è difficile, non porta introiti, in un secondo mondo tecnologico come quello italiano una finezza simile viene messa all’ultimo posto

Ancora più importante, perchè tocca lo scopo di SniffJoke, è la natura di un simile strumento d’analisi. Le tecnologie pensate per analizzare giga e giga di traffico vengono utilizzati per effettuare analisi massive sui contenuti trasmessi via internet. Si può chiamare ipotetico “grande fratello”, o “sistema di statistica sulle conoscenze medie” o “tecnologia di schedatura digitale con associazione contenuto/ip anonimo”: non importa, uno strumento d’analisi massivo cercherà di catturare la più grande fetta di sessioni, non la minore. SniffJoke rende le sessioni TCP del vostro computer parte di quell’anomalia difficilmente catturabile, proteggendosi da questa insensata violazione dei diritti umani.

Per quanto riguarda gli IDS la situazione è leggermente diversa. La quantità di dati per la quale sono previsti è inferiore e la possibilità che un attaccante utlizzi delle tecniche di evasion è più frequente, inoltre, gli scopi differenti dei due strumenti presuppongono una sensibilità maggiore a problemi di sicurezza spicciola come questo.

Riporto anche questa parte, essenziale:

Questo strumento non protegge da:

  • un’analisi targettizzata
  • Se le forze dell’ordine vi stanno controllando, non sarà con questo programma che eluderete i loro controlli
  • Allo stesso modo se una spia è stata assoldata per impadronirsi dei vostri segreti
  • Questo strumento non può ne serve a proteggere chi ha dei problemi più grossi di una connessione TCP
  • Le analisi del traffico su un target specifico non sono bypassabili: una volta catturato il traffico esso verrà analizzato da chi ha ricevuto la commissione e si tratterà di una persona in grado di dire quale pacchetto è vero e quale no

Questo strumento protegge da:

  • analisi massive o
  • attacchi portati con motivazioni criminose, se dirette ad una massa di potenziali vittime e non ad un target specifico

Questo strumento illude le macchine, non le persone.

Terminate le premesse, avviso che il post presente verrà aggiornato con spiegazioni migliori, analisi di funzionamento sulla rete e altro che mi verrà in mente.

Il file è online nella sezione tools di s0ftpj.org, qui il .tar.gz

Qui sotto i passi d’installazione e d’uso:

debian:~# md5sum sniffjoke-0.1.tar.gz
3197b8ba5c32b72df0aaa5632ee21e2c sniffjoke-0.1.tar.gz
debian:~# sha1sum sniffjoke-0.1.tar.gz
ee64d8da7cc157120d9c8651be2ad7e947346d97 sniffjoke-0.1.tar.gz

Una volta preso il pacchetto sniffjoke-0.1.tar.gz e l’ultima versione di ulogd, la 1.24, lo si spostano in una directory d’appoggio:

debian:/tmp# ls -l *.tar*
-rw-r--r-- 1 root root 17220 2007-02-20 18:42 sniffjoke-0.1.tar.gz
-rw-r--r-- 1 root root 177398 2007-02-20 18:43 ulogd-1.24.tar.bz2
debian:/tmp# tar jxf ulogd-1.24.tar.bz2
debian:/tmp# tar zxf sniffjoke-0.1.tar.gz
debian:/tmp# cd ulogd-1.24
debian:/tmp/ulogd-1.24# ./configure && make && cd ..
debian:/tmp# mv sniffjoke-0.1 ulogd-1.24
debian:/tmp# cd ulogd-1.24/sniffjoke-0.1/
debian:/tmp/ulogd-1.24/sniffjoke-0.1# make
work only as subdir of ulogd, take a look README
cp -f ../pcap/Makefile Makefile.pcap
sed -e's/PCAP/SNIFFJOKE/g' -e's/\-lpcap//g' Makefile.pcap > Makefile.sniffjoke
make -f Makefile.sniffjoke
make[1]: Entering directory `/tmp/ulogd-1.24/sniffjoke-0.1'
gcc -g -O2 -Wall -DULOGD_CONFIGFILE="/usr/local/etc/ulogd.conf" -I/lib/modules/`uname -r`/build/include -I.. -I../libipulog/include -I../include -fPIC -o ulogd_SNIFFJOKE_sh.o -c ulogd_SNIFFJOKE.c
ld -shared -o ulogd_SNIFFJOKE.so ulogd_SNIFFJOKE_sh.o -lc
make[1]: Leaving directory `/tmp/ulogd-1.24/sniffjoke-0.1'
debian:/tmp/ulogd-1.24/sniffjoke-0.1# make install
make -f Makefile.sniffjoke install
make[1]: Entering directory `/tmp/ulogd-1.24/sniffjoke-0.1'
/usr/bin/install -c -m 755 -d /usr/local/lib/ulogd
/usr/bin/install -c -m 755 *.so /usr/local/lib/ulogd
make[1]: Leaving directory `/tmp/ulogd-1.24/sniffjoke-0.1'

Terminata l’installazione si deve modificare leggermenete il file di configurazione in /usr/local/etc/ulogd.conf
(ulogd supporta vari plugin, se l’utente li vuole usare). Noi lasciamo ulogd_BASE.so ed aggiungiamo ulogd_SNIFFJOKE.so

#plugin="/usr/local/lib/ulogd/ulogd_BASE.so"
#plugin="/usr/local/lib/ulogd/ulogd_LOGEMU.so"
#plugin="/usr/local/lib/ulogd/ulogd_OPRINT.so"
#plugin="/usr/local/lib/ulogd/ulogd_MYSQL.so"
#plugin="/usr/local/lib/ulogd/ulogd_PGSQL.so"
#plugin="/usr/local/lib/ulogd/ulogd_SQLITE3.so"
#plugin="/usr/local/lib/ulogd/ulogd_PCAP.so"
plugin="/usr/local/lib/ulogd/ulogd_SNIFFJOKE.so"

Piu in basso si trova una parte di confiugrazione dedicata alle opzioni dei plugin. ogni sezione inizia con [NOMEPLUGIN], ignorate le opzioni degli altri, ed in fondo mettete:

[SNIFFJOKE]
file="/tmp/sniffjoke.log"
port="25,110,80,443,6667"
user="vecna"

file è il nome del file di log, dove un output abbastanza verboso descrive l’injection e il tracciamento delle sessioni.
port prende una stringa come opzione, deve contenere una sequenza di porte TCP alle quali applicare le regole di evasion. in quello specifico caso ce ne sono 5, non ci sono limitazioni. Attenzione pero’, ogni porta corrisponde ad una regola iptables che verrà creata. e’ anche possibile specificare dei range di porte, ad esempio “1-20000,30000″ include con 2 regole di iptables tutte le porte dalla 1 alla 20000 e la porta 30000.
user il nome dell’utente al quale applicare le regole di evasion. E’ necessario non sia root e ci sia UN utente specificato. Questa limitazione è dovuta a delle problematiche di hijacking spiegate più dettagliatamente nel README.

Prima di usarlo verificare che siano presenti i moduli per netfilter ipt_owner ed ipt_ULOG.

Una volta pronti i componenti:

debian:/tmp# ls -l sniffjoke.log
-rw-r--r-- 1 root root 940256 2007-02-20 19:00 sniffjoke.log
debian:/tmp# > sniffjoke.log
debian:/tmp# lsmod | grep ipt_
ipt_owner 2048 0
ipt_ULOG 7812 0
debian:/tmp# iptables -L
[vuoto]
debian:/tmp# ulogd -d
Tue Feb 20 19:01:50 2007 <3> ulogd.c:308 registering interpreter `raw'
Tue Feb 20 19:01:50 2007 <3> ulogd.c:308 registering interpreter `oob'
Tue Feb 20 19:01:50 2007 <3> ulogd.c:308 registering interpreter `ip'
Tue Feb 20 19:01:50 2007 <3> ulogd.c:308 registering interpreter `tcp'
Tue Feb 20 19:01:50 2007 <3> ulogd.c:308 registering interpreter `icmp'
Tue Feb 20 19:01:50 2007 <3> ulogd.c:308 registering interpreter `udp'
Tue Feb 20 19:01:50 2007 <3> ulogd.c:308 registering interpreter `ahesp'
Tue Feb 20 19:01:50 2007 <3> ulogd.c:363 registering output `sniffjoke'
debian:/tmp# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ULOG icmp -- anywhere anywhere icmp time-exceeded ULOG copy_range 0 nlgroup 1 queue_threshold 1
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ULOG tcp -- anywhere anywhere tcp dpt:smtp OWNER UID match vecna ULOG copy_range 0 nlgroup 1 queue_threshold 1
ULOG tcp -- anywhere anywhere tcp dpt:pop3 OWNER UID match vecna ULOG copy_range 0 nlgroup 1 queue_threshold 1
ULOG tcp -- anywhere anywhere tcp dpt:www OWNER UID match vecna ULOG copy_range 0 nlgroup 1 queue_threshold 1
ULOG tcp -- anywhere anywhere tcp dpt:https OWNER UID match vecna ULOG copy_range 0 nlgroup 1 queue_threshold 1
ULOG tcp -- anywhere anywhere tcp dpt:ircd OWNER UID match vecna ULOG copy_range 0 nlgroup 1 queue_threshold 1
debian:/tmp#
debian:/tmp# su - vecna
vecna@debian:~$ lynx -dump http://www.s0ftpj.org >/dev/null
vecna@debian:~$ exit
logout
debian:/tmp# ls -l sniffjoke.log
-rw-r--r-- 1 root root 4088 2007-02-20 19:03 sniffjoke.log
debian:/tmp# killall ulogd
debian:/tmp# iptables -L
[vuoto]
debian:/tmp#
debian:/tmp# grep inject sniffjoke.log
10 sniffjoke_hack: invalid (tcp) checksum with RST inject - [remote CWND could be resize]
11 sendto: injecting 40 byte hack 1
15 sniffjoke_hack: invalid (tcp) checksum with RST inject - [remote CWND could be resize]
[...]

buon divertimento :)

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]