Archivi tag: ip

PMTUD e TCP MSS

Topologia di massima

Due filiali interconnesse mediante un tunnel GRE/IPSEC instaurato sfruttando le rispettive linee ADSL. In particolare, sul sito A sono presenti diversi client che hanno necessità di “dialogare” con un server Web posto nel sito B.

Problema

I client accedono al server Web remoto con estrema lentezza e molte delle richieste effettuate vanno in timeout. Nella fattispecie, trattasi di un problema legato alla MTU (Maximum Transmission Unit) configurata sulle interfacce dei router delle 2 filiali, che provoca la suddetta sintomatologia.

Un po’ di teoria

Ma cos’è l’MTU? Essa, molto semplicemente, definisce la dimensione massima (in byte) di un pacchetto (o di un frame) che può attraversare una determinata interfaccia di rete. Ad esempio, nel caso del protocollo IP (layer 3) parliamo generalmente di 1500 byte, mentre nel caso del protocollo Ethernet (layer 2) la MTU è pari a 1526 byte (1500 byte “ereditati” dal protocollo IP + 22 byte di instestazione Ethernet e 4 byte di CRC). Quest’ultima è sicuramente la più rognosa, in quanto molto spesso gli switch sono unmanaged e quindi non è possibile accorgersi immediatamente dei cosiddetti frame giant, che vegnono quindi scartati “silenziosamente” provocando una comunicazione “a singhiozzo” (vedi questo post per ulteriori dettagli).

Per quanto riguarda invece la MTU IP, si avranno sicuramente dei problemi nel caso in cui:

1) i valori configurati sulle interfacce del router A e del router B differiscono tra di loro (in gergo parliamo di MTU mismatch);

2) lungo il cammino tra router A e il router B esiste un segmento la cui MTU è inferiore rispetto a quella configurata sui 2 router.

Nel primo caso possiamo correre ai ripari molto velocemente, configurando un valore di MTU identico sulle interfacce dei router delle 2 filiali. Ad esempio, possiamo definire la MTU di una data interfaccia utilizzando il comando:

Router(config-if)# ip mtu <valore in byte>

Nel secondo caso, invece, occorre fare un po’ di diagnostica ed eventualmente utilizzare delle configurazioni ad hoc.

In entrambi i casi i pacchetti che superano la MTU più bassa verranno “frammentati” e ricostruiti in fase di ricezione. Ovviamente tale operazione, oltre a causare un overhead sui router coinvolti, provocherà dei seri problemi a livello 4 (TCP) e superiori, inficiando in modo notevole l’accesso al servizio da parte degli utenti.

PMTUD

Per evitare quindi che si verifichi un’eccessiva frammentazione è stato messo a punto un meccanismo tale per cui un router riuscirà ad accorgersi automaticamente della presenza di un valore di MTU inferiore rispetto a quello configurato sulla propria interfaccia, riducendo di conseguenza la dimensione dei pacchetti che intende inoltrare. Tale meccanismo prende il nome di Path MTU Discovery, abbreviato in PMTUD. Più in dettaglio, essa si basa sull’invio/ricezione di messaggi ICMP unreachable type 3 code 4 ( vedi qui per ulteriori dettagli): se la MTU dei pacchetti ricevuti da un router supera la dimensione massima definita sulla propria interfaccia in ricezione, esso procederà con l’inoltro del suddetto messaggio verso il router mittente. In tal modo, quest’ultimo si accorgerà di quanto sta avvenendo e ridurrà di conseguenza la MTU in modo da riuscire ad “attraversare” il router interessato.

PMTUDOra, occorre precisare che non è tutto oro ciò che luccica, nel senso che molto spesso i pacchetti ICMP unreachable vengono disabilitati sia in TX che in RX (in questo caso si parla di PMTUD blackhole). Ad esempio, nel caso dei dispositivi di casa Cisco, essi sono disabilitati di default:

Router#sh ip int dia0 | i ICMP
  ICMP redirects are never sent
  ICMP unreachables are never sent
  ICMP mask replies are never sent

Il perchè di tale configurazione è presto detto: per loro stessa natura, i messaggi ICMP consentono di ottenere informazioni “sensibili” sulla rete target e possono anche essere utilizzati per generare attacchi di tipo DoS/DDoS. Infatti, se un utente malevolo facesse in modo di “sollecitare” la generazione dei messaggi ICMP unreachable da parte del router oggetto dell’attacco, riuscirebbe certamente a sovraccaricarlo, poichè la generazione del suddetto tipo di messagistica avviene a livello di CPU. Come workaround è comunque possibile settare un rate limit specifico, ad esempio:

Router(config)# ip icmp rate-limit unreachable df 500

dove 500 rappresenta il numero di millisecondi che deve intercorrere tra la generazione di un messaggio ICMP unreachable e quello successivo.

A titolo di cronaca, per abilitare i suddetti messaggi su una data interfaccia è sufficiente digitare il comando:

Router(config-if)# ip unreachable

Identificare il valore di MTU corretto: metodo trial and error

Occorre precisare che esiste un modo empirico per determinare la dimensione della MTU più piccola presente lungo il percorso tra il router A ed il router B. Esso si basa sull’utilizzo del comando ping dotato delle flag -f (che imposta a 1 il bit do not fragment nell’header IP) e -l (che imposta la dimensione del solo payload). Se ad esempio la MTU configurata sulla scheda di rete del nostro PC (con Windows 7 a bordo) fosse pari a 1500 byte, potremmo utilizzare il comando:

C:\Users\pippo> ping 192.168.1.1 -f -l 1472

dove 1472 è il massimo payload definibile senza che vi sia frammentazione, poichè ad esso verranno sommati i 20 byte di intestazione IP e gli 8 byte di instestazione ICMP (per un totale di 1500 byte). Utilizzando un payload di 1473 byte, la nostra scheda ci indicherà che abbiamo superato la MTU attraverso il seguente output:

C:\Users\pippo>ping 192.168.1.1 -l 1473 -f

Esecuzione di Ping 192.168.1.1 con 1473 byte di dati:
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.

Tale metodo può essere utilizzato per identificare la MTU di interesse, abbassando di volta in volta la dimensione del payload fino a quando al posto del suddetto messaggio verranno visualizzati dei semplici ICMP echo reply.

Una piccola nota a margine: nel caso in cui si volesse utilizzare questa metodologia direttamente dalla CLI del router Cisco, è possibile utilizzare il seguente comando:

ping 192.168.1.1 source fa0/0 df-bit size 1500

dove 1500, in questo caso, rappresenta la dimensione totale del messaggio ICMP echo request (e non del solo payload come avveniva nel caso di Windows 7).

TCP MSS

L’acronimo MSS sta per Maximum Segment Size e rappresenta la dimensione massima (in byte) che può avere il payload (e solo il payload) di un segmento TCP. Il valore di default è 1460, ovvero 1500 byte di MTU meno i 20 byte di instestazione TCP ed i 20 byte di intestazione IP. Nel caso in cui la MTU più piccola relativa al percorso tra A a B fosse inferiore a quella di default, è possibile “forzare” il valore di MSS (in gergo parliamo di MSS clamping). Ad esempio, per i router Cisco potremo utilizzare il comando:

Router(config-if)# ip tcp adjust-mss <byte>

dove i byte da utilizzare sono dati dalla MTU più piccola meno 40 byte.

Un caso pratico (e molto diffuso tra gli end user) in cui l’MSS clamping torna davvero utile riguarda il protocollo PPPoE, che usa una MTU pari a 1492 byte (a differenza del PPPoA la cui MTU è quella classica, ovvero 1500 byte). In tal caso si può procedere con questa configurazione sull’interfaccia dia0:

Router(config-if)# ip mtu 1492
Router(config-if)# ip tcp adjust-mss 1452

Spero di aver fatto un minimo di chiarezza sul concetto di MTU e su quanto esso sia importante nell’ambito della comunicazione client/server basata sul protocollo TCP e superiori.

Alla prossima.

Traffico TCP sulla porta 0

Qualche giorno fa Nagios mi ha segnalato un allarme di sicurezza che mi ha lasciato alquato basito:

When a syslog message is generated by the device a SEC info IPACCESSLOGP list 102 denied tcp 77.223.136.170(0) - 95.245.162.62(0), 1 packet 9:5:46:40.62

In soldoni, l’ACL attiva sull’interfaccia dialer (WAN) del mio router ha “scartato” un segmento TCP proveniente dall’IP 77.223.136.170 (porta 0) e diretto al mio (vecchio) IP pubblico (ovvero 95.245.162.62, porta 0).

Ora, è sufficiente avere un minimo di dimestichezza con lo stack TCP/IP per capire che l’anomalia sta proprio nella porta sorgente ed in quella di destinazione. Infatti, la porta 0 è riservata ed il suo impiego può avvenire per i motivi (leciti) più disparati.

Ad esempio, nel caso in cui il pacchetto IP (formato da header + payload) superi la MTU del link che deve attraversare, esso subirà un processo specifico, denominato “frammentazione”.

In particolare, essendo l’header TCP parte del payload IP (per via dell’incapsulamento – vedi immagine sottostante), ciascun frammento potrebbe contenere la suddetta intestazione per intero o solo parzialmente. Nel primo caso, l’header TCP originario si troverebbe soltanto nel primo frammento, mentre tutti gli altri conterrebbero la sola intestazione IP (dotata di ID specifico del frammento, offset per la ricostruzione del traffico in fase di ricezione – dimensione e bit MFMore Fragment – pari a 0 o 1 a seconda che si tratti dell’ultimo frammento o meno).

encaps

Più in generale, la porta TCP/UDP pari a 0 potrebbe stare a significare, molto semplicemente, assenza di layer 4 (basti pensare al protocollo ICMP).

Per quanto riguarda, invece, l’uso malevolo della porta 0, possiamo distinguere 3 macro-tipologie di casi:

1) Attacchi di tipo fingerprint. Essi si basano sul presupposto che spesso e volentieri le ACL non possono essere definite in modo tale da droppare esplicitamente il traffico in ingresso sulla porta 0 (TCP o UDP), ergo puntare ad essa è un modo abbastanza efficace (ma non infallibile) per ottenere info sulla tipologia di router oggetto di interesse (OS fingerprint – leggete questo per ulteriori dettagli);

2) Attacchi volti ad “aggirare” le ACL. Ad esempio, forzando la frammentazione del pacchetto IP ed agendo sul campo offset,  si potrebbe riuscire, in teoria, a sovrascrivere parte dell’intestazione TCP originaria (che punta ad una porta di destinazione “lecitamente” raggiungibile dall’esterno, come potrebbe essere la 25 per il protocollo SMTP) con una porta non accessibile dall’esterno (ad esempio la 23 per il protocollo Telnet). Per ulteriori dettagli su tale tipologia di attacco (denominato tiny overlapping fragment attack) leggete questo.

3) Attacchi di tipo DoS/DDoS. Forzando la frammentazione dei pacchetti IP sottostanti al layer 4 (TCP/UDP) si potrebbe riuscire a “sovraccaricare” il router di destinazione, soprattutto per via dell’overhead dovuto all’attività di “ricostruzione” del traffico. Inoltre, puntando ad una porta non lecita, ad esempio la 0, lo si costringerebbe ad inviare dei messaggi ICMP Port Unreachable (se abilitati sull’interfaccia), sovraccaricandolo ulteriormente.

Della casistica appena illustrata credo che l’allarme ricada, molto banalmente, negli attacchi di tipo fingerprint. Ovviamente ho alzato il livello di attenzione per evitare “brutte” sorprese in futuro.

Vi terrò comunque aggiornati.

Aggiornamento 1

A quanto pare si è trattato proprio di un portscan/fingerprint. Infatti, dopo circa 5 giorni dallo scan sulla porta TCP 0, ho registrato il seguente traffico:

Jan 25 15:29:15 192.168.2.1 1738: 001735: Jan 25 15:29:14.483 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 77.223.136.170(443) -> 79.31.118.x(43616), 1 packet
Jan 25 15:29:17 192.168.2.1 1739: 001736: Jan 25 15:29:15.988 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(256) -> 79.31.118.x(43617), 1 packet
Jan 25 15:29:18 192.168.2.1 1740: 001737: Jan 25 15:29:17.200 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(111) -> 79.31.118.x(43617), 1 packet
Jan 25 15:29:19 192.168.2.1 1741: 001738: Jan 25 15:29:18.204 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 77.223.136.170(1106) -> 79.31.118.x(43616), 1 packet
Jan 25 15:29:20 192.168.2.1 1742: 001739: Jan 25 15:29:19.204 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(700) -> 79.31.118.x(43617), 1 packet
Jan 25 15:29:20 192.168.2.1 1743: 001740: Jan 25 15:29:20.208 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 77.223.136.170(3493) -> 79.31.118.x(43616), 1 packet
Jan 25 15:29:22 192.168.2.1 1744: 001741: Jan 25 15:29:21.213 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(726) -> 79.31.118.x(43617), 1 packet
Jan 25 15:29:24 192.168.2.1 1746: 001743: Jan 25 15:29:23.365 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(777) -> 79.31.118.x(43618), 1 packet
Jan 25 15:29:26 192.168.2.1 1747: 001744: Jan 25 15:29:25.046 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(111) -> 79.31.118.x(43618), 1 packet

Aggiornamento 2

In data 26 Gennaio ho ricevuto un altro pacchetto da/verso la suddetta porta:

When a syslog message is generated by the device a SEC info IPACCESSLOGP list 101 denied tcp 23.236.147.202(0) - 79.31.118.x(0), 1 packet 0:14:52:02.45

Vediamo se tra qualche giorno il nuovo IP sorgente utilizzerà lo stesso ordine di port probing del suo predecessore.

Aggiornamento 3

Come volevasi dimostrare, a distanza di qualche ora è arrivato il port probing vero e proprio:

Jan 27 18:36:33 192.168.2.1 19380: 019433: Jan 27 18:36:32.479 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 23.236.147.202(139) -> 79.31.118.x(46096), 1 packet
Jan 27 18:36:35 192.168.2.1 19381: 019434: Jan 27 18:36:34.475 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 23.236.147.202(1002) -> 79.31.118.x(46097), 1 packet
Jan 27 18:36:36 192.168.2.1 19382: 019435: Jan 27 18:36:35.500 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 23.236.147.202(2701) -> 79.31.118.x(46095), 1 packet
Jan 27 18:36:36 192.168.2.1 19383: 019436: Jan 27 18:36:36.500 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 23.236.147.202(11967) -> 79.31.118.x(46095), 1 packet
Jan 27 18:36:38 192.168.2.1 19384: 019437: Jan 27 18:36:37.552 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 23.236.147.202(1494) -> 79.31.118.x(46095), 1 packet
Jan 27 18:36:39 192.168.2.1 19385: 019438: Jan 27 18:36:38.556 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 23.236.147.202(8021) -> 79.31.118.x(46095), 1 packet
Jan 27 18:36:43 192.168.2.1 19387: 019440: Jan 27 18:36:42.353 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 23.236.147.202(139) -> 79.31.118.x(46097), 1 packet
Jan 27 18:36:48 192.168.2.1 19388: 019441: Jan 27 18:36:47.154 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 23.236.147.202(139) -> 79.31.118.x(46095), 1 packet

Anche in questo caso le porte oggetto dell’attacco sono quelle > 1023. Ho quindi fatto qualche modifica all’ACL configurata sulla dia0 del mio router, sostituendo la regola:

access-list 101 permit tcp any gt 1023 any log

con:

access-list 101 permit tcp any gt 1023 any established log

in modo tale da consentire il traffico proveniente dalle porte > 1023 solo se si riferiscono a delle connessioni già esistenti.

Aggiornamento 4

Sono riuscito a ricreare parzialmente la suddetta tipologia di traffico, utilizzando un apposito tool denominato hping, il quale è in grado di forgiare dei pacchetti RAW/TCP/UDP/ICMP da impiegare durante le operazioni di OS fingerprint e non solo.

Ad esempio, mediante il comando:

[root@linuxbox ~]# hping3 -S -V <mio indirizzo IP>

sono riuscito a generare una sfilza di pacchetti TCP recanti i classici 40 byte di header, payload 0 e flag SYN settata a 1, la cui destinazione proprio è la famigerata porta 0.

Di seguito riporto il tracciato tcpdump da locale (grazie al quale si può notare che la porta sorgente è una porta alta, ovvero maggiore di 1023, e che la porta di destinazione è sempre la 0):

09:41:14.967184 IP 192.168.1.1.1232 > 79.31.118.x.0: Flags [S], seq 2094000106, win 512, length 0
09:41:15.967305 IP 192.168.1.1.1233 > 79.31.118.x.0: Flags [S], seq 517260399, win 512, length 0
09:41:16.967425 IP 192.168.1.1.1234 > 79.31.118.x.0: Flags [S], seq 399923675, win 512, length 0
09:41:17.967477 IP 192.168.1.1.1235 > 79.31.118.x.0: Flags [S], seq 725026004, win 512, length 0
09:41:18.967573 IP 192.168.1.1.rmtcfg > 79.31.118.x.0: Flags [S], seq 1830159741, win 512, length 0
09:41:19.967638 IP 192.168.1.1.1237 > 79.31.118.x.0: Flags [S], seq 342672970, win 512, length 0

Mentre il log generato dal mio router è il seguente:

Apr  3 09:39:35 192.168.2.1 108805: 108943: Apr  3 08:39:34.979 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1232) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:37 192.168.2.1 108807: 108945: Apr  3 08:39:36.979 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1233) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:39 192.168.2.1 108808: 108946: Apr  3 08:39:38.980 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1234) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:41 192.168.2.1 108809: 108947: Apr  3 08:39:40.980 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1235) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:43 192.168.2.1 108810: 108948: Apr  3 08:39:42.981 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1236) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:45 192.168.2.1 108811: 108949: Apr  3 08:39:44.977 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1237) -> 79.31.118.x(0), 1 packet

Invece, forzando a 0 la porta sorgente del suddetto traffico (e mantenendola tale per tutta la durata del test – opzione -k) attraverso il comando:

[root@linuxbox ~]# hping3 -S -VV -s 0 -k <mio indirizzo IP>

sono riuscito ad intercettarlo localmente come dimostrato dal seguente tracciato:

10:32:21.495218 IP 192.168.1.1.0 > 79.31.118.x.0: Flags [S], seq 1600061111, win 512, length 0
10:32:22.495334 IP 192.168.1.1.0 > 79.31.118.x.0: Flags [S], seq 965785080, win 512, length 0
10:32:23.495411 IP 192.168.1.1.0 > 79.31.118.x.0: Flags [S], seq 677172521, win 512, length 0
10:32:24.495492 IP 192.168.1.1.0 > 79.31.118.x.0: Flags [S], seq 473418678, win 512, length 0

ma è stato successivamente scartato dal router sorgente, ergo non è mai giunto a destinazione.

Nei prossimi giorni proverò a ripetere il test utilizzando il router di un vendor differente.

sniffer.sh: script bash per l’individuazione dei site grabber

Scenario

Supponiamo che il vostro sito sia diventato oggetto delle attenzioni di un grabber (di cui non si conosce l’indirizzo IP pubblico), che ogni X tempo ne preleva il contenuto forzosamente.

Supponiamo, inoltre, che il suddetto grabber sia abbastanza intelligente da coprire le proprie tracce “spoofando” lo user agent in modo da apparire come un client lecito.

590x300

Nel caso in cui non si abbiano a disposizione strumenti di log analysis avanzati quali Splunk, l’unica alternativa per individuare l’IP pubblico del grabber consiste nel crearsi degli strumenti ad-hoc,  in grado di fare un conteggio del numero di hit per ciascun IP pubblico che ha contattato il nostro sito.

In soldoni si tratta di un semplice scrip bash, che riporto di seguito.

#!/bin/bash

filename1="/var/log/sniffer.log"

filename2="/var/log/sources.log"

filename3="/var/log/sources_sorted.log"

filename4="/var/log/sources_sorted_by_hits.log"

if [ -e $filename1 ];then

cat /dev/null > $filename1

fi

if [ -e $filename2 ];then

cat /dev/null > $filename2

fi

if [ -e $filename3 ];then

cat /dev/null > $filename3

fi

if [ -e $filename4 ];then

cat /dev/null > $filename4

fi

echo ""

echo -e "33[32mSniffing traffic... Press CTRL+C to stop"

echo -e "33[37m"

START=$(date +%s);

iftop -i eth0 -n -f 'port (80 or 443)' -t > $filename1

echo ""

read -p "Press [Enter] key to continue..."

END=$(date +%s);

ELAPSED_TIME=$((END-START))

echo -e "33[32mShowing hit number provided in $ELAPSED_TIME seconds, ordered by source..."

echo -e "33[37m"

cat $filename1 | grep '<=' | awk '{ print $1 }' > $filename2

cat $filename2 | sort -u > $filename3

while read line

do
 hits=`cat $filename2 | grep $line | wc -l`

host=`host $line`

echo "hits for IP $line ($host): $hits" >> $filename4

done < $filename3

cat $filename4 | sort -k 5 -nr

exit 0

Esso si basa principalmente sul software iftop e, una volta lanciato, rimane in ascolto sulle porte di interesse (nel nostro caso la TCP/80 e la TCP/443), per poi stilare una “classifica” di IP pubblici in base al numero di hit che hanno prodotto durante il tempo di osservazione.

Come informazione aggiuntiva, per ogni IP viene ricavato anche il suo FQDN (attraverso il comando host), in modo da individuare ancora più facilmente la provenienza del grabber.

Per maggiore chiarezza, ecco un esempio di output relativo al suddetto script:

hits for IP 87.18.215.154 (154.215.18.87.in-addr.arpa domain name pointer host154-215-dynamic.18-87-r.retail.telecomitalia.it.): 18
hits for IP 84.223.145.17 (17.145.223.84.in-addr.arpa domain name pointer dynamic-adsl-84-223-145-17.clienti.tiscali.it.): 23
hits for IP 84.222.212.172 (172.212.222.84.in-addr.arpa domain name pointer dynamic-adsl-84-222-212-172.clienti.tiscali.it.): 23
hits for IP 79.18.99.217 (217.99.18.79.in-addr.arpa domain name pointer host217-99-dynamic.18-79-r.retail.telecomitalia.it.): 24
hits for IP 2.35.156.49 (49.156.35.2.in-addr.arpa domain name pointer net-2-35-156-49.cust.vodafonedsl.it.): 21
hits for IP 188.87.64.235 (235.64.87.188.in-addr.arpa domain name pointer static-235-64-87-188.ipcom.comunitel.net.): 23
hits for IP 151.45.153.218 (218.153.45.151.in-addr.arpa domain name pointer adsl-ull-218-153.45-151.net24.it.): 14

Inoltre, consultando il file /var/log/sources_sorted_by_hits.log, sarà possibile ricavare la lista degli IP/FQDN ordinati (in modo decrescente) in base al numero delle hit che hanno effettuato.

Una volta individuato l’IP che ci interessa non ci resta che bloccarlo utilizzando, ad esempio, iptables:

iptables -I INPUT -s <ip del grabber> -j DROP

ed abbiamo finito.

Alla prossima.

WI-FI IP camera made in China: ennesima stranezza

Ok, avete ragione, sono un maledettissimo freak control. Però non è colpa mia se questo aggeggio continua a comportarsi in modo strano. Infatti, oltre a questa anomalia, ho notato che ogni tanto prova a contattare l’ennesimo server cinese, questa volta un nameserver (almeno sulla carta).

Inoltre, molto probabilmente quel nameserver (sempre se di nameserver si tratta) è di proprietà del costruttore di questi aggeggi, tant’è che un semplice whois mi ha rivelato le seguenti informazioni:

nightfly@nightbox:~$ whois 211.154.141.240
% [whois.apnic.net node-1]
% Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html

inetnum:        211.154.128.0 - 211.154.159.255
netname:        ChinaMotion
country:        CN
descr:          China Motion Network Communication
descr:          9F,Yu Hua Industrial & Trading Building,Bao Gang Rd.
descr:          Luo Hu District,Shenzhen, Guangdong Province
admin-c:        BY158-AP
tech-c:         BY158-AP
status:         ALLOCATED PORTABLE
mnt-by:         MAINT-CNNIC-AP
mnt-lower:      MAINT-CNNIC-AP
mnt-irt:        IRT-CNNIC-CN
mnt-routes:     MAINT-CNCGROUP-RR
changed:        hm-changed@apnic.net 20060523
source:         APNIC

person:         Binghua Yang
nic-hdl:        BY158-AP
e-mail:         idc-service@hotmail.com
address:        9F,Yu Hua Industrial & Trading Building,Bao Gang Rd.Luo
address:        Hu District,Shenzhen
phone:          +86-0755-82189782
fax-no:         +86-755-82189789
country:        CN
changed:        shenzhi@cnnic.cn 20041126
changed:        ipas@cnnic.net.cn 20070514
mnt-by:         MAINT-CN-CMNET
source:         APNIC

Ma bando alle ciance, ecco cosa succede sniffando un pò di pacchetti con tcpdump:

18:13:28.222925 IP 10.1.x.x.3072 > 8.8.8.8.53: 125+ A? dns.camcctv.com. (33)
        0x0000:  4500 003d 62c7 4000 4011 bcd3 0a01 0105  E..=b.@.@.......
        0x0010:  0808 0808 0c00 0035 0029 af81 007d 0100  .......5.)...}..
        0x0020:  0001 0000 0000 0000 0364 6e73 0763 616d  .........dns.cam
        0x0030:  6363 7476 0363 6f6d 0000 0100 01         cctv.com.....
18:13:28.288413 IP 8.8.8.8.53 > 10.1.x.x.3072: 125 1/0/0 A[|domain]
        0x0000:  4500 004d a392 0000 2f11 ccf8 0808 0808  E..M..../.......
        0x0010:  0a01 0105 0035 0c00 0039 28b5 007d 8180  .....5...9(..}..
        0x0020:  0001 0001 0000 0000 0364 6e73 0763 616d  .........dns.cam
        0x0030:  6363 7476 0363 6f6d 0000 0100 01c0 0c00  cctv.com........
        0x0040:  0100 0100 0009 6800 04d3 9a8d            ......h.....
18:13:28.325038 IP 10.1.x.x.3072 > 211.154.141.240.2011: UDP, length 84
        0x0000:  4500 0070 0000 4000 4011 cdec 0a01 0105  E..p..@.@.......
        0x0010:  d39a 8df0 0c00 07db 005c e3b5 4d4f 5f48  ...........MO_H
        0x0020:  0000 0000 3738 2d41 352d 4444 2d30 342d  ....78-A5-DD-04-
        0x0030:  4138 2d33 4500 0000 3130 2e31 2e31 2e35  A8-3E...10.1.x.x
        0x0040:  0000 0000 0000 0000 0000 0000            ............

Che significa tutto ciò? Brevemente: dapprima manda una query DNS di tipo A al suo nameserver primario (8.8.8.8), richiedendo l’IP associato all’hostname dns.camcctv.com:

18:13:28.222925 IP 10.1.x.x.3072 > 8.8.8.8.53: 125+ A? dns.camcctv.com

La risposta alla suddetta query è la seguente:

18:13:28.288413 IP 8.8.8.8.53 > 10.1.x.x.3072: 125 1/0/0 A[|domain]

Una volta individuato l’indirizzo IP di dns.camcctv.com (ovvero 211.154.141.240) procede con l’invio, verso la porta UDP 2011, del proprio MAC address e del proprio indirizzo IP locale.

Facendo due più due il conto è presto fatto: con il dyndns abilitato di default, l’IP pubblico del network a cui la telecamera appartiene diventa di dominio pubblico (e soprattutto di dominio del costruttore). A questo aggiungeteci le info che manda a quel nameserver e praticamente, nel caso in cui ci fosse una qualche backdoor all’interno del codice dell’interfaccia Web di cui è dotata, il costruttore (o chi per lui) avrebbe la possibilità di accedere liberamente alla nostra IP camera. A questo aggiungeteci l’eventualità che tutto il traffico in ingresso su quella porta del nameserver potrebbe essere loggato, rilevando quindi l’indirizzo IP pubblico della rete a cui appartiene la telecamera.

Ora, poichè tale device ha un server FTP integrato, mi sono preso la briga di accedervi e di scaricare in locale tutte le pagine Web (.htm) che concorrono al funzionamento dell’interfaccia di gestione. Inutile dire che non ci ho trovato granchè, anche perchè tutte le modifiche alla configurazione vengono effettuate mediante delle chiamate AJAX a determinate pagine *.xml (che, naturalmente, non sono scaricabili).

Infatti, per capire cosa sia possibile fare tramite delle semplici chiamate alle suddette pagine, è sufficiente consultare questo documento:

IPCamera_AJAX (English Translation) – GadgetVictimsCom.pdf

Per completezza, se volete provare ad accedere al suddetto server FTP (della vostra telecamera, non di certo della mia) è necessario:

1) utilizzare un client ben preciso, ovvero CuteFTP (con tutti gli altri, client FTP Linux da CLI, client FTP Windows da CLI, FireFTP, eccetera, il demone della telecamera crasha miseramente);

2) loggarsi con username MayGion e con password maygion.com (credenziali case sensitive e non modificabili – dove maygion è il produttore del firmware).

Come ho risolto? Di nuovo, regola Iptables del tipo:

iptables -A FORWARD -i eth1 -o eth0 -p udp -d 211.154.141.240 –dport 2011 -j DROP

Sto anche monitorando tutto il traffico diretto alla porta HTTP della telecamera, vediamo cosa ne verrà fuori.

Alla prossima.

Aggiornamento del 16/12/2012

A quanto pare l’hostname dns.camcctv.com è qualcosa di hard coded all’inteno dei sorgenti del firmware (a giudicare dal questo 3D). Inoltre, sembra che si tratti dell’ennesimo servizio di DDNS ma, non essendoci alcuna opzione che mi consenta di disabilitarlo via interfaccia Web, lo terrò comunque in DROP.

ddosinfo: script per la creazione automatica di ACL Cisco contro gli attacchi DDoS

In questo post vi ho mostrato un piccolo scrip per l’individuazione della nazionalità relativa agli IP sorgenti di un attacco DDoS. Avevo già preannunciato alcune modifiche, ovvero la generazione automatica delle ACL Cisco e l’aggiunta di un menù interattivo. Bhè, così è stato.

acl, cisco, acl standard, acl estese, acl nominali, bash, ddos, whois, IP, netblock

Per prima cosa installiamo il tool ipcalc, che ci servirà per calcolare le wildmask da impostare sulle ACL:

nightfly@nightbox:~$ sudo apt-get install ipcalc

Successivamente creiamo un file testuale vuoto su cui incolleremo il contenuto dello scrip e rendiamolo eseguibile:

nightfly@nightbox:~$ touch ddosinfo

nightfly@nightbox:~$ chmod +x ddosinfo

Non ci resta che copiarci dentro le seguenti direttive:

#!/bin/bash
touch ipinfo
touch target
touch parsed
touch acl
touch target_pari
touch target_dispari
touch target_parsed

while read line
do
        whois -F $line >> ipinfo
done < tlog

while read line
do
    locin=`echo $line | grep "*in"`
    loccy=`echo $line | grep "*cy"`
    if [[ -n "$locin" || -n "$loccy" --; then
        echo "$locin$loccy"  >> target
    fi
done < ipinfo

cat target | awk 'NR%2==1' >> target_dispari
cat target | awk 'NR%2==0' >> target_pari

paste target_dispari target_pari | grep -v "IT" >> target_parsed

while read line
do
        block=`echo $line | grep "*in" | sed s/*in://g`
    if [ -n "$block" ]; then
               wild1=`ipcalc $block | awk '{ print $1 }' | sed s/deaggregate//g`
        wild2=`ipcalc -b $wild1 | awk 'BEGIN { FS = "Wildcard: " } ; { print $2 }' | tr 'n' ' ' | sed 's/^[ t]*//;s/[ t]*$//;'`
        wild3=`ipcalc -b $wild1 | awk 'BEGIN { FS = "Address: " } ; { print $2 }' | sed 's/^[ t]*//;s/[ t]*$//'`
        echo "$wild3 $wild2" >> parsed
    fi
done < target_parsed

echo "Seleziona il tipo di ACL:"

echo "1 - standard"
echo "2 - estesa"
echo "3 - nominale"

read scelta;

if [ $scelta == 1 ]; then
    while true;
    do
    echo "Inserisci l'identificativo dell'acl (1-99):"
   
    read numero;
   
    if [[ $numero =~ ^([1-9]|[1-9][0-9])$ --;then
        while true;
        do
            echo "Scegli il protocollo (ip-tcp-udp):"
            read protocollo;
            if [[ $protocollo =~ ^(ip|tcp|udp)$ --;then
                while true;
                do
                    echo "Vuoi attivare il logging? (S/N):"
                        read logging;
                    if [ $logging == "S" ];then
                        while read line
                        do
                            network=`echo $line | awk 'BEGIN { FS = " " } ; { print $1 }'`
                            wildcard=`echo $line | awk 'BEGIN { FS = " " } ; { print $2 }'`
                            echo "access-list $numero deny $protocollo $network $wildcard any log" >> acl
                        done < parsed
                        break
                    else
                        if [ $logging == "N" ];then
                            while read line
                                        do
                                                network=`echo $line | awk 'BEGIN { FS = " " } ; { print $1 }'`
                                wildcard=`echo $line | awk 'BEGIN { FS = " " } ; { print $2 }'`
                                                echo "access-list $numero deny $protocollo $network $wildcard any" >> acl
                                        done < parsed
                        break
                        fi
                    fi
                done
            fi
            break
        done
    break
    fi
    done
fi

if [ $scelta == 2 ]; then
    while true;
    do

    echo "Inserisci l'identificativo dell'acl (100-199 oppure 2000-2699):"
    read numero;

    if [[ $numero =~ ^(1[0-9][0-9]|2[0-6][0-9][0-9])$ --;then
        while true;
        do
            echo "Scegli il protocollo (ip-tcp-udp):"
            read protocollo;
            if [[ $protocollo =~ ^(ip|tcp|udp)$ --;then
                while true;
                do
                    echo "Vuoi attivare il logging? (S/N):"
                        read logging;
                    if [ $logging == "S" ];then
                        while read line
                        do
                            network=`echo $line | awk 'BEGIN { FS = " " } ; { print $1 }'`
                            wildcard=`echo $line | awk 'BEGIN { FS = " " } ; { print $2 }'`
                            echo "access-list $numero deny $protocollo $network $wildcard any log" >> acl
                        done < parsed
                        break
                    else
                        if [ $logging == "N" ];then
                            while read line
                                        do
                                                network=`echo $line | awk 'BEGIN { FS = " " } ; { print $1 }'`
                                wildcard=`echo $line | awk 'BEGIN { FS = " " } ; { print $2 }'`
                                                echo "access-list $numero deny $protocollo $network $wildcard any" >> acl
                                        done < parsed
                        break
                        fi
                    fi
                done
            fi
            break
        done
    break
    fi
    done
fi

if [ $scelta == 3 ]; then

    while true;
    do
    echo "Inserisci il nome dell'acl:"
    read nome;
    if [[ $nome =~ [[:alpha:-- --;then
        while true;
        do
            echo "Scegli il protocollo (ip-tcp-udp):"
            read protocollo;
            if [[ $protocollo =~ ^(ip|tcp|udp)$ --;then
                while true;
                do
                    echo "Vuoi attivare il logging? (S/N):"
                        read logging;
                    if [ $logging == "S" ];then
                        while read line
                        do
                            network=`echo $line | awk 'BEGIN { FS = " " } ; { print $1 }'`
                            wildcard=`echo $line | awk 'BEGIN { FS = " " } ; { print $2 }'`
                            echo "access-list $numero deny $protocollo $network $wildcard any log" >> acl
                        done < parsed
                        break
                    else
                        if [ $logging == "N" ];then
                            while read line
                                        do
                                                network=`echo $line | awk 'BEGIN { FS = " " } ; { print $1 }'`
                                wildcard=`echo $line | awk 'BEGIN { FS = " " } ; { print $2 }'`
                                                echo "access-list $numero deny $protocollo $network $wildcard any" >> acl
                                        done < parsed
                        break
                        fi
                    fi
                done
            fi
            break
        done
    break
    fi
    done
fi

rm ipinfo
rm parsed
rm target_*

exit 0;

Tale scrip consente di scegliere tra 3 tipoligie di ACL (tutte per il protocollo IP), ovvero:

1) standard;

2) estese;

3) nominali.

Le ACL generate verranno salvate all’interno del file acl, mentre gli IP sorgenti da analizzare vanno posizionati nel file tlog. Non vi rimane dunque che copiare il contenuto del file acl ed incollarlo nel firewall/router, sotto il menù di configurazione (config#) e successivamente associare l’access control list appena creata all’interfaccia target.

Avrete certamente notato che il codice non è dei più semplici per via del parsing massiccio che si è reso necessario. Tuttavia non scoraggiatevi, se avete delle domande (ed individuate eventuali falle/miglioramenti) non esitate a contattarmi.

A presto.

DDoS: script bash per individuare la nazionalità degli IP sorgenti dell’attacco

Per arginare un attacco DDoS è necessario, prima di tutto, individuare quali sono gli IP pubblici da cui proviene. In secondo luogo, occorre capire se il sito vittima basa il proprio “business” esclusivamente su visite italiane. In questo caso, per realizzare delle opportune ACL in modo da filtrare il traffico in ingresso, si deve capire quali sono i netblock stranieri da interdire. Per fare ciò ho realizzato un piccolo scrip bash che legge gli IP da un file di testo (ricavati, ad esempio, analizzando i log del Firewall o del Web server) e ne individua il relativo netblock (e la nazionalità).

 

ddos,bash,script,linux,netblock,netmask,ip

Ecco lo scrip:

#!/bin/bash

touch ipinfo
touch target

while read line
do
        whois -F $line >> ipinfo
done < tlog

while read line
do
        locin=`echo $line | grep "*in"`
        loccy=`echo $line | grep "*cy"`
        if [[ -n "$locin" || -n "$loccy" --; then
                echo "$locin$loccy" >> target
        fi
done < ipinfo

rm ipinfo

exit 0;

Ovviamente è ancora ad una versione alpha (0.1). Appena avrò tempo provvederò ad aggiungere il calcolo automatico delle netmask e la creazione automatizzata della relative ACL Cisco (con un minimo di interattività).

Alla prossima.

NB: il file testuale tlog deve contenere un solo IP sorgente per riga.