==============================================================================
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
--------------------[ previous ]---[ index ]---[ next ]---------------------

------------------------[ PR0GETT0 0N0S3NDAi - PARTE II ]---------------------
-----------------------------------[ FuSyS ]----------------------------------

       ---[ G U I D A   N E W B I E   A L L'  I P  S P O O F I N G ]---

                                t r a t t o  d a

              ---[ T C P / I P  T O O L S  U N L I M I T E D ]---

                              ---[ P A R T E II ]---

NO(C)1998 FuSyS
A scopo informativo e di apprendimento. Ricerca e conoscenza. E, perche' no ?!
Dedicato in particolar modo a tutti i vari newbie e lama del cosiddetto
sottobosco italiano. Perche' piu' nessuno debba chiedere "Tu sai spoofare ?"
D'altronde come al solito, capira' solo chi vuole e puote :) [certo di mio
non ci metto nulla per facilitare eccessivamente :P]

#############################################################################
DISCLAIMER
Tutto il materiale contenuto in questo articolo e' di pubblico dominio. Le
spiegazioni, le descrizioni, i consigli, il codice, sono rielaborazioni,
creazioni e sunti evinti da RFC, libri, FAQ e letture di molto codice.
NULLA E' TOTALMENTE NUOVO O RIVELAZIONE DI QUEL CH'ERA COPERTO DA SEGRETO
MILITARE. I vari ingredienti del progetto sono reperibili in rete.
#############################################################################

CONSIGLO DELLA SETTIMANA
Non chiedete via mail, IRC, talk, irl, (...), se potete chieder[m,c]i una
cosa. Chiedetela e basta. Semplicemente pensate a quello che chiedete e
come lo domandate.

Siete fortunati :) .... essendo questa la seconda parte del progetto non
vi dovrete sorbire alcuna introduzione. D'altra parte non ho neanche
intenzioni di farvi il riassunto delle puntate precedenti. Leggetevi i
primi capitoli di questo interessante HOWTO :) Intanto eccovi i soliti
requisiti di base :)

PREREQUISITI            Conoscenza di base di Internet, TCP/IP, *nix e C
                        Come sarebbe a dire che non ne avete ?! =;)

Spero abbiate davvero letto la prima parte. Le strutture IP e TCP devono
ormai esservi familiari. Concetti come sniff ed hijack anche, spero. Ho
ripetuto in piu' articoli come creare un pacchetto e chiedere al kernel di
lanciarlo in rete per conto nostro. Oggi facciamo il salto nel buio :)


NOTA: in tutta la seconda parte vi prego di considerare come relativo al
problema posto il termine facilita'. Non stiamo parlando di piccolezze, ma
di un attacco comunque complesso.

------[ G U A R D A  M A ' ... S E N Z A  O C C H I ! ]------ 

Come da molti auspicato, sperato, invocato [ma vaaaaaa ...] ecco la
seconda parte di 0N0S3NDAi dedicata allo SP00FiNG nobile; quello cieco.
Nonostante anche le tecniche spiegate nella prima parte abbiano in se'
quel particolare sapore di alta stregoneria tipico dell'hacking a basso
livello dei protocolli di rete, quello cieco e' ancora piu' miracoloso e
rispettato, ricercato dai newbie cosi' come dagli amministratori di
sistema, che spesso non colgono le effettive possibilita' di questo tipo
di attacchi.

La peculiarita' di questo tipo di hackeraggio e' effettivamente la totale
ed assoluta mancanza di ogni controllo sulla connessione che intendiamo
spoofare. Noi non abbiamo alcuna collocazione nelle LAN dei due punti
della connessione desiderata e non siamo neanche su alcuno degli hop
possibili tra i due IP che ci interessano.

Avendo ben chiaro l'handshake di una connessione TCP secondo il 3-way, e'
ovvio che:

- non saremo in grado di sniffare, conoscere o carpire il SEQ iniziale del
  server (o ISN) in modo da poter rispondere con un ACK appropriato

- non potremo neanche sapere se la porta TCP interessata dalla connessione
  sia effettivamente aperta

- se anche la connessione fosse stabilita, non vedremmo alcuna risposta,
  dato od alcunche' da parte del peer

In fondo questo e' abbastanza semplice da capire. Considerando la nostra
macchina come A (attaccante), B il bersaglio da attaccare e S la macchina
da spoofare, e considerando l'impossibilita' di essere sul percorso tra B
e S, avremo:

		A (S) ---------------------------> B
						   |
		   S <-----------------------------/

Il nostro bersaglio ricevera' molto volentieri la nostra richiesta di
connessione, ma rispondera' inviando i suoi pacchetti verso la macchina
che davvero corrisponde all'IP che noi stiamo spoofando. Noi non solo
non vedremo i pacchetti, ma neanche la risposta di S. Non potremo agire
direttamente in alcun modo su tali pacchetti, come abbiamo invece avuto
modo di fare nella prima parte di 0N0S3NDAi.

Come vi avevo detto, S rispondera' con un RST ai pacchetti di B, non
avendo davvero iniziato lui la connessione. Questo interromperebbe ogni
nostra velleita' di attacco.

Quindi, prima ancora di iniziare :) abbiamo gia' due pesanti problemi.

1) la nostra cecita'
2) i RST della box spoofata

Ovviamente ci sono alcuni escamotage :P altrimenti non ci sarebbe alcun
motivo per questo articolo, no ?! D'altra parte e' bene sappiate che per
il primo problema NON ci sono soluzioni ottimali, ne' tantomeno
infallibli. In alcuni casi direi che ci si avvicina per asintoto alla
impossibilita' di portare a termine la connessione spoofata alla cieca.

Ad ogni modo cerchiamo di vedere come poter risolvere questi due problemi.

------[ P R E D I Z I O N E  T C P  S E Q  N U M B E R ]------

Avrete letto questa frase chissa' quante volte in chissa' quanti articoli,
testi, sorgenti, e via dicendo :) Ebbene, e' proprio questo il succo dello
spoof alla cieca. Anzi, esiste addirittura un RFC deputato alla lotta
contro questo tipo di attacco tecnico. L' RFC1948 datato Maggio 1996 (!!!)
e scritto dal famoso S.Bellovin [se non sapete chi sia, la domanda spontanea 
e' "ma dove siete vissuti ?", se davvero volete seriamente fare hack] e'
intitolato, molto sobriamente :), Difendersi dagli attacchi contro i
numeri di sequenza. Sostanzialmente in questo RFC si propone un nuovo
meccanismo di generazione dell'ISN o Initial Sequence Number (lo
ricordavate dalla prima parte, vero ?! :PPP) per evitare che questo possa
essere predetto.

Effettivamente il succo dell' iP SP00FiNG cieco e' proprio questo: la
predizione del numero di sequenza TCP in modo da poter stabilire lo stesso
una connessione senza essere in grado di visualizzare i pacchetti
inviatici dal server.

Strano a dirsi, nonostante siano passati 3 anni buoni da questo RFC, vi
posso garantire che la percentuale di macchine FACILMENTE VULNERABILI ad
uno spoofing cieco sono decisamente ancora MOLTE. Evidentemente possiamo
anche aspettarci che implementazioni su vasta scala di procedure
criptografiche di autenticazione delle connessioni siano ancora molto
lontane .... :O

Per poter prevedere il ISN dovremo essere in grado di sapere come venga
generato questo valore a 32bit dal computer remoto che stiamo per
attaccare. Ebbene c'e' un solo modo per saperlo remotamente purtroppo.
Ovvero stabilire un contatto con questa macchina. Questo vuol dire che
dovremo lasciare una impronta digitale sul bersaglio. Ma questo non deve
preoccuparci piu' di tanto, in quanto il tipo di impronta e'
impercettibile sulla maggior parte dei sistemi oggi connessi in rete, e
sinceramente sulla stragrande totalita' di quelle macchine ancora
facilmente vulnerabili allo spoof cieco. Una volta approfondita la nostra
consapevolezza sulla generazione remota dell'ISN potremo prevedere le
future risposte ed attaccare di conseguenza.

------[ R S T  ?  N O  G R A Z I E ]------

Il secondo problema ci vede giustamente, a seconda del lato da cui si
osserva la situazione :P, in balia della box che spoofiamo per quanto
riguarda la riuscita dell'attacco. Spesso le soluzioni a problemi che i
newbie considerano ostici o stregoneschi :), deriva dalla semplice
constatazione del problema da risolvere e da una corretta analisi dello
stesso. In questo caso, se S risponde con un RST, allora la semplice
azione che dobbiamo realizzare e': S NON DEVE INVIARE RST. PUNTO. No :),
non sto scherzando. E' tutto qui.

Vediamo un attimo. Come puo' una macchina non inviare RST ?

Puo' avere lo stack TCP/IP sputtanato. Improbabile (ma solo xche' non
voglio dire impossibile :). Puo' essere scollegata dalla rete, o spenta.
In questo caso i pacchetti di B si perderanno nel void e non ci saranno
problemi per il nostro attacco, in quanto lo stack di B pensera' prima ad
una congestione e insistera' con i suoi pacchetti fino ad un timeout,
entro il quale noi avremo risposto con la nostra predizione del SEQ. Puo'
non esistere proprio [sottopossibilita' della precedente, in cui usiamo un
IP spoofato NON associato ad alcuna macchina, in modo da risultare cmq
IRRINTRACCIABILI]. Oppure la macchina deve essere occupata, congestionata
e quindi incapacitata a rispondere prima del nostro attacco.

Il metodo da manuale, che anche Topolino nei suoi inserti <Conosci la rete
con Minnie> probabilmente riporta, e' la cosiddetta Tempesta di SYN, Syn
Flood per gli anglofoni. Non e' ovviamente il solo metodo, ne esistono
altri. Importante e' l'obiettivo e non necessariamente il metodo in questo
specifico caso.

------[ L'  A T T A C C O ]------

Prima di analizzare meglio la questione della predizione del SEQ, dei RST
di S, e dell'inoculamento dei nostri dati vediamo in soldoni come viene
portato l'attacco tipo. Usero' un attacco realmente avvenuto per poter
spiegare cosa sia e come venga portata avanti una azione di SP00FiNG cieco.
L'attacco e' quello di Kevin Mitnick del 25 Dicembre 1994 [non so voi, ma
io il 25/12 sono a mangiare come un maiale :)]

############################################################################
CONSIDERAZIONE STORIOGRAFICA: questo e' quanto e' successo realmente nella
famosa questione Mitnick dell'attacco al sistema di Shimomura. Ogni altra
versione e' fallace, e facilmente smontabile. Queste righe sono una
riscrittura esplicativa ed informativa basata sui fatti cosi' come riportati
dallo stesso T.S. in una mail tecnica. Ora finalmente potete raccontare ai
nipotini la storia e ridere alle spalle di chi se ne inventa una versione
diversa ogni sera che accede ad IRC :P
############################################################################

All'inizio, non interessante per noi, Mitnick esegue una serie di
operazioni di spionaggio :) in modo da poter capire se esista qualche
serie di fiducia tra alcuni sistemi di Shimomura. Relazione esistente in
questo caso tra server e x-terminal. Dopo aver tratto quanto gli serve, fa
partire una marea di richieste di connessioni con flag SYN da un IP
spoofato e non assegnato alla porta 513 del server di Shimomura.

 130.92.6.97.601 > server.login: S 1382726961:1382726961(0) win 4096
 130.92.6.97.602 > server.login: S 1382726962:1382726962(0) win 4096
 130.92.6.97.603 > server.login: S 1382726963:1382726963(0) win 4096
 130.92.6.97.604 > server.login: S 1382726964:1382726964(0) win 4096
 130.92.6.97.605 > server.login: S 1382726965:1382726965(0) win 4096
 130.92.6.97.606 > server.login: S 1382726966:1382726966(0) win 4096
 ... 

in questo modo la coda di connessione di server viene riempita, e con l'IP
spoofato non assegnato, ogni risposta con ACK di server andra' a finire
nel vuoto richiedendo un meccanismo di ritrasmissione e timeout.

Dopo, arrivano delle richieste di connessione verso un terminaleX di norma
servito da server, da apollo.it.luc.edu. Queste richieste usano dei numeri
di sequenza progressivi il che suggerisce che NON siano prodotti dallo
stack TCP/IP della macchina quanto da un codice apposito. Evidentemente lo
scopo e' quello di apprendere informazioni sulle caratteristiche di
generazione del SEQ da parte del terminaleX. Ogni SYN/ACK del terminale
viene accolto da un RST per evitare di saturare la coda di connessione
anche del bersaglio.

1)
 apollo.it.luc.edu.1000 > x-terminal.shell: S 1382726990:1382726990(0) win 4096
 x-terminal.shell > apollo.it.luc.edu.1000: S 2021824000:2021824000(0) 
 ack 1382726991 win 4096
 apollo.it.luc.edu.1000 > x-terminal.shell: R 1382726991:1382726991(0) win 0
2)
 apollo.it.luc.edu.1001 > x-terminal.shell: S 1382726991:1382726991(0) win 4096
 x-terminal.shell > apollo.it.luc.edu.1001: S 2021952000:2021952000(0)
 ack 1382726992 win 4096
 apollo.it.luc.edu.1001 > x-terminal.shell: R 1382726992:1382726992(0) win 0
3)
 apollo.it.luc.edu.1002 > x-terminal.shell: S 1382726992:1382726992(0) win 4096
 x-terminal.shell > apollo.it.luc.edu.1002: S 2022080000:2022080000(0)
 ack 1382726993 win 4096
 apollo.it.luc.edu.1002 > x-terminal.shell: R 1382726993:1382726993(0) win 0
...

come potete vedere le risposte di x-terminal sono sempre aumentate di
128000, valore questo costante nella generazione del ISN. A questo punto
avviene una richiesta di connessione da server.shell verso x-terminal.
Ovviamente e' spoofata da Mitnick, e quanto x-terminal risponde con un ACK
il vero server non puo' rispondere in quanto la coda della porta 513 e'
satura, congestionata dalla tempesta di SYN inviata dall'attaccante.
Ovviamente l'ACK esatto arriva spoofato da Mitnick che e' in grado di
prevedere il valido ISN di x-terminal dopo aver lanciato una ventina di
sonde da apollo.it.luc.edu .....

 server.login > x-terminal.shell: S 1382727010:1382727010(0) win 4096
 server.login > x-terminal.shell: . ack 2024384001 win 4096
 
A questo punto l'attaccante ha una connessione a senso unico verso
x-terminal, e puo' quindi inserire i suoi dati.

 server.login > x-terminal.shell: P 0:2(2) ack 1 win 4096
 server.login > x-terminal.shell: P 2:7(5) ack 1 win 4096
 server.login > x-terminal.shell: P 7:32(25) ack 1 win 4096

Questi vengono inseriti in successione, senza prestare attenzione alle
risposte di x-terminal, il bersaglio, in quanto non ci interessano. Non
abbiamo bisogno ne' dell'output dei nostri comandi ne' di altre
informazioni della shell remota. L'importante e' che i nostri dati vengano
passati all'applicazione remota. Quelli inseriti da Mitnick furono i
famosissimi "echo + + >>/.rhosts". Dopodiche' viene chiusa la connessione.

 server.login > x-terminal.shell: . ack 2 win 4096
 server.login > x-terminal.shell: . ack 3 win 4096
 server.login > x-terminal.shell: F 32:32(0) ack 3 win 4096
 server.login > x-terminal.shell: R 1382727043:1382727043(0) win 4096
 server.login > x-terminal.shell: R 1382727044:1382727044(0) win 4096

PUNTO. Questo e' quanto e' successo :) Dal mio punto di vista non credo
proprio che Mitnick sia stato il primo a portare questo genere di attacco.
e probabilmente il software necessario non era neanche suo. Ha avuto la
sfortunata occasione di farsi bello con un esperto di sicurezza, cosa che
mi lascia perplesso sulle sue reali priorita' ..... ma ad ogni modo questa
e' un'altra storia. [e cmq non condivido cio' che gli e' stato inflitto
dal governo americano]

------[ N U M E R I  D I  S E Q U E N Z A ]------

OK :) prima o poi bisogna arrivarci. Il succo dell'attacco e' la
predizione del numero di sequenza. Una parentesi: non mi stanchero' mai di
far capire alla gente che nell'hijack di una connessione, la predizione,
facile o difficile che sia, dei numeri di sequenza NON C'ENTRA UNA MAZZA.
Quello e' campo dello SP00FiNG vedente e NON e' un problema ma una
semplice banalita' sapendo cosa fare e come farlo. D'altra parte un
hijack mediante SP00FiNG cieco NON E' POSSIBILE in linea di massima.
Infatti in quel caso noi abbiamo bisogno di sapere come procedano entrambi
i lati della connessione in materia di SEQ e ACK. Ma se non abbiamo modo
di vedere la connessione non possiamo neanche sapere se uno dei due peer
stia inviando dati, ne' quali o quanti. Un hijack alla cieca sarebbe
possibile solo indovinando gli ISN di entrambe le macchine, indovinando i
dati trasmessi (nel caso di login remoti anche gli errori di battitura :O)
e la temporizzazione della connessione. Fate un po' voi :)

Lo SP00FiNG cieco puo' intervenire in una connessione in corso solo per
distruggerla mediante RST nel caso di stack TCP/IP FALLATI che non
controllino i numeri di sequenza nel caso di flag RST con IP e porte
corrette. Uno stack di questo tipo dovrebbe essere quello di Digital Unix
4.0b ed inferiori, ma non ho una macchina per eseguire questo tipo di
test. Come al solito donazioni di Alpha con DUNIX sono ben accette :P

Il corretto ISN e' la mecca del nostro attacco. E se in guerra dobbiamo
conoscere il nostro nemico, allora in questo caso dobbiamo sapere dove ISN
nasca. Se non vi spaventano la matematica ed il C stretto, potete gettare
un occhio nel sorgente /usr/src/linux/drivers/char/random.c [linux2.2.x]
per rendervi conto come linux sia estremamente resistente alla predizione
del ISN. Direi che linux da questo punto di vista sia immune a simili
attacchi.

64K -> OLDIES BUT GOLDIES

D'altra parte nello stack derivante da BSD le cose non vanno cosi'.
Secondo l'RFC793 il valore di ISN dovrebbe:

- essere subordinato ad un clock, la cui frequenza ne influenzerebbe
  l'incremento
- l'incremento dovrebbe essere di 125000 ogni mezzo secondo

In realta' moltissimi sistemi, anche oggi, rientrano nella cosiddetta
regola aurea dei 64k. Secondo questa regola il valore viene incrementato
di 64000 ogni mezzo secondo, poco piu' della meta' di quanto specificato
dall'RFC793, quindi 128000 ogni secondo. Nel caso di nuove connessioni
questo valore viene ulteriormente incrementato di 64000 la maggior parte
delle volte [alcuni stack lo aumentano di 128000 od altri valori costanti]
permettendo quindi di osservare un pattern abbastanza uniforme e regolare
dei SEQ.

Ora come sara' ben chiaro a tutti, x-terminal attaccato da Mitnick faceva
uso della regola dei 64k per il suo ISN ed ha quindi permesso all'attacco
di andare in porto senza particolari difficolta' al di fuori del blocco
della coda di server.

Questo tipo di generazione ISN avviene ancora nella quasi totalita' delle
macchine OSF/1, Digital Unix, SunOS (non Solaris), OS/2. Dal momento che
non sono poche le macchine presenti in Internet a soddisfare questa
regola, si puo' dire che lo SP00FiNG relativamente semplice sia ancora
possibile.

TICK-TACK SEQ

Un altro sistema di generazione tiene invece conto sempre di un clock, ma
utilizzando le piu' svariate costanti di incremento. Con questo metodo,
dopo l'inizializzazione pseudo random al boot della macchina, il SEQ viene
incrementato ogni tot unita' di tempo. Nelle vecchie versioni del kernel
di linux questo avveniva ogni microsecondo, con incrementi di una unita'.
Fa parte di questo tipo di generazione lo stack di Windows NT, tra gli
altri.

Questo sistema non e' affatto sicuro. In effetti e' abbastanza semplice
correlare il possibile ISN a precedenti connessioni ed al clock di sistema
valutando il tempo intercorrente tra la nostra box ed il nostro bersaglio.
Ovvero il tempo tra l'invio del pacchetto e la ricezione di una risposta
alla nostra sonda.

RANDOM ISN

L'unico sistema veramente sicuro (almeno fino ad ora) e' quella della
generazione casuale del SEQ per ogni nuova connessione. Questo permette
di non poter correlare un ISN all'altro mediante l'uso di un numero
maggiore di sonde. Questo rende quasi impossibile lo SP00FiNG cieco contro
questi sistemi. In questa categoria abbiamo linux :) [anche se con una
eccezione di cui parlero' dopo e che ha dato nuovo significato al concetto
di falsa sicurezza].

NB: esistono varianti che usano sempre lo STESSO ISN. Non ne ho trovate in
giro, ma probabilmente ne esistono ancora. Giusto a titolo storiografico,
mandatemi email per segnalarmele, grazie :) Se invece trovate stampanti,
quickcam o router che lo facciano, beh lo sapevo :) [ad ogni modo info su
router con ISN==0 sono sempre molto ben accette :)]

VEDO, PREVEDO, STRAVEDO :P

Come capire di quale sistema di generazione faccia uso un sistema remoto ?
Essenzialmente, come nell'analisi dell'attacco a Shimomura, si tratta solo
di studiare le risposte del server alle nostre sonde. In questo caso una
sonda non e' altro che un pacchetto TCP con flag SYN con il nostro reale
IP (altrimenti non siamo in grado di ricevere le risposte).

Piuttosto che riscoprire l'acqua calda, e commentare un mio codice (cosa
che invece faremo per una tecnica di spoof concreta), analizzero' le
funzioni implementate da fyodor in nmap v2 per lo studio dei vari ISN.
Precisamente guardiamo in osscan.c [nmap 2.02] tra le funzioni di
riconoscimento remoto degli OS mediante impronte TCP/IP; non e' mio
interesse ne' compito in questo testo spiegarvi come funzioni il
riconoscimento remoto. Potrete tranquillamente leggervi il sorgente prima
o poi :). L'importante e' vedere intorno [ripeto, la mia e' la 2.02] alla
riga 266@1208 la funzione di controllo dei vari SEQ ricevuti come risposta
dal sistema remoto.

Classe RANDOM - difficolta' 9999999 :

	for(i=0; i < si->responses - 1; i++) {
         if (MOD_DIFF(si->seqs[i+1],si->seqs[i]) > 50000000) {
           si->class = SEQ_TR;
           si->index = 9999999;
           break;
         }

in questo caso fyodor decide di valutare la differenza passante tra le
varie coppie sequenzialmente possibili di ISN ricevuti. Se questa e'
maggiore di 50000000 allora il generatore remoto fa parte della classe TR,
Truly Random o realmente casuale. Poco da fare in questo caso. MOD_DIFF
serve a calcolare le differenze tenendo conto del fatto che il primo
numero possa non necessariamente essere maggiore del secondo.

Classe COSTANTE - difficolta' 0 :))) :

	if (seq_gcd == 0) {
        	si->class = SEQ_CONSTANT;
        	si->index = 0;
        } 

seq_gcd viene calcolato in base alle differenze tra ISN ottenuti da tot
pacchetti di risposta. La funzione necessaria per ottenere gcd e
calcolarne valore a seconda dei SEQ e' get_gcd_n_ulong() che a sua volta
chiama euclid_gcd() per descriverne le deviazioni. Quello che stiamo cercando 
e' il massimo comun divisore delle differenze tra le coppie di numeri di
sequenza che abbiamo ottenuto con la scansione. Una volta ottenuto questo
siamo in grado di valutare l'andamento del SEQ remoto. In questo caso ogni
volta abbiamo un ISN uguale. Lo SP00FiNG sara' come bere un bicchiere di
RedBull :) facile e piacevole :P

Classe 64k - difficolta' 1 :) :

	else if (seq_gcd % 64000 == 0) {
       		si->class = SEQ_64K;
       		si->index = 1;
     	} 

se il modulo 64000 di questi SEQ e' uguale a 0 siamo in presenza della
legge aurea dei 64k. Incrementi di 64000 o suoi multipli ogni tick di 
clock e nuova connessione.

Classe i800 - difficolta' 10 :

	else if (seq_gcd % 800 == 0) {
       		si->class = SEQ_i800;
       		si->index = 10;
     	} 

in questo caso ci interessa il modulo 800. Questo tipo di generazione,
altrettanto semplice e' pero' meno comune.

Classe TIME DEPENDENT - difficolta' < 75 :

	else if (si->class == SEQ_UNKNOWN) {
       		seq_avg_inc = (0.5) + seq_avg_inc / (si->responses - 1);
       		for(i=0; i < si->responses -1; i++)       {
			seq_inc_sum += pow(MOD_DIFF(seq_diffs[i],seq_avg_inc),
					 2);
       }

se non abbiamo trovato alcuna delle corrispondenze gia' esposte allora
calcoliamo l'incremento medio dei vari ISN ottenuti, otteniamo il minore
delle differenze tra questo incremento medio e la differenza in esame e lo
eleviamo al quadrato. Questo sistema presentato anche da coder@reptile
serve per ottenere migliori valori su cui discriminare.

       seq_inc_sum /= (si->responses - 1);
       si->index = (unsigned long) (0.5 + pow(seq_inc_sum, 0.5));
       if (si->index < 75) {
         si->class = SEQ_TD;
       }

a questo punto se l'indice che otteniamo dal rapporto tra l'incremento
medio e le risposte ottenute e' inferiore a 75 allora possiamo
classificare la generazione come relazionata ad un clock. Le box Microsoft
NT sono in questa categoria. Le altre invece saranno nella classe ad
incremento casuale con difficolta' medie tra 76 e 9999999.

Visto che comunque non siete mai contenti ne' purtroppo, almeno per la
maggior parte di voi, decisi a far tutto da voi, ecco un semplice codice
per la scansione dei numeri di sequenza di un host remoto. Li mostra, ne
calcola le differenze tra coppie consecutive e discrimina in base alle
regole consuete. Il controllo delle regole e' solo leggermente modificato
dalle funzioni di nmap. Questo perche' non ho molto tempo a disposizione e
comunque quelle regole sono valide :) Badate bene. Sarebbe possibile farlo
ad occhio visto il display di questo codice, ma cosi' e' molto piu'
semplice.

---------- snip ----------
/************************************************************************
* SEQprobe.c            Semplice sonda per evidenziare la generazione   *
*			dell' Initial Sequence Number [ISN], necessario *
*			passo per iniziare un attacco di IP Spoofing	*
*			cieco mediante previsione del SEQ successivo.	*
*									*
*                               NO(C)1998 FuSyS TCP/IP Tools Unlimited  *
*                                                      fusys@s0ftpj.org *
************************************************************************/
/************************************************************************
* USO:                	Beh, se proprio non vi va di leggere il codice	*
*			almeno leggetevi l'articolo Progetto 0N0S3NDAi  *
*			parte II presente sul numero 6 della ezine BFi.	*
*			Butchered From inside e' prelevabile dall'URL:	*
*			http://www.s0ftpj.org/bfi/          		*
************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/if_ether.h>
#include <net/if.h>
#include <ioctls.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <math.h>
#include <getopt.h>

#ifndef MIN
#define MIN(x,y) (((x)<(y))?(x):(y))
#endif
#ifndef DIFF
#define DIFF(a,b) (u_long)(MIN((u_long)(a)-(u_long)(b),(u_long)(b)-(u_long)(a)))
#endif

#define MAXPROBES 		10
#define MTU                     1500
#define IP_HEADER	        20
#define TCP_HEADER           	20
#define PSEUDO_HEADER		12
#define INITSOURCE		10000
#define INITSEQ			24375400

int sp_fd, IF_LEN, iflink;
char *IF_NAME;
unsigned long localip, remoteip;
unsigned long seqs[MAXPROBES];
unsigned long seqs_diff[MAXPROBES];
unsigned long seqs_gcd;
unsigned long seqs_incr;
unsigned long seqs_sum;
unsigned short port;

struct syn_pk {
	struct iphdr ip;
	struct tcphdr tcp;
};

struct pseudo_pk {
        unsigned long saddr;
        unsigned long daddr;
        unsigned char zero;
        unsigned char proto;
        unsigned short len;
};

u_long nameResolve(char *hostname)
{
  struct in_addr addr;
  struct hostent *hostEnt;

  if((addr.s_addr=inet_addr(hostname)) == -1) {
    if(!(hostEnt=gethostbyname(hostname))) {
        printf("Name Resolution Error:`%s`\n",hostname);
        exit(0);
    }
    bcopy(hostEnt->h_addr,(char *)&addr.s_addr,hostEnt->h_length);
  }
  return addr.s_addr;
}

char *ntoa(unsigned long ip) {
        static char buff[18];
        char *p;
        p = (char *) &ip;
        sprintf(buff, "%d.%d.%d.%d",
                (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
        return(buff);
}

/* la solita routine di checksum */
u_short in_cksum(u_short *ptr, int nbytes)
{
  register long           sum;
  u_short                 oddbyte;
  register u_short        answer;

  sum = 0;
  while (nbytes > 1)
  {
    sum += *ptr++;
    nbytes -= 2;
  }

  if (nbytes == 1)
  {
    oddbyte = 0;           
    *((u_char *) &oddbyte) = *(u_char *)ptr;
    sum += oddbyte;
  }

  sum  = (sum >> 16) + (sum & 0xffff);   
  sum += (sum >> 16);                   
  answer = ~sum;         

  return((u_short) answer);
}

void raw(void)
{
    int opt=1;

    if((sp_fd=socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) <0){
        perror("\nRAW() Problemi inizializzazione socket raw\n");
        exit(0);
    }
    if(setsockopt(sp_fd, IPPROTO_IP, IP_HDRINCL, &opt, sizeof(opt)) <0){
            perror("RAW() Problemi inizializzazione HDRINCL\n");
            exit(0);
    }
}

int tap(char* device,int mode)
{
    int fd;
    struct ifreq ifr;

    if((fd=socket(AF_INET, SOCK_PACKET, htons(0x3))) <0){
        perror("TAP() Problemi inizializzazione SOCK_PACKET\n");
        exit(0);
    }

    strcpy(ifr.ifr_name,device);
    if (ioctl (fd, SIOCGIFADDR, &ifr) < 0) {
        perror("TAP() Impossibile ottenere l'IP locale !\n");
        exit(1);
    }
    memcpy ((void *) &localip, (void *) &ifr.ifr_addr.sa_data + 2, 4);

    if(!mode){
        close(fd);
        return(0);
    }
    else return(fd);
}

void fire_syn(unsigned short source, unsigned long seq)
{
	struct sockaddr_in sin;
        int shoot;
	struct syn_pk syn;
	struct pseudo_pk *ppk_p;
	char checkbuff[MTU];

	memset(&syn, 0, sizeof(syn));
	memset(checkbuff, 0, MTU);
	ppk_p=(struct pseudo_pk *)checkbuff;

	syn.tcp.source=source;
        syn.tcp.dest=port;
        syn.tcp.seq=seq;
	syn.tcp.doff=5;
	syn.tcp.syn=1;
	syn.tcp.window=htons(0x7000);

	ppk_p->saddr=localip;
        ppk_p->daddr=remoteip;
        ppk_p->zero=0;
        ppk_p->proto=IPPROTO_TCP;
        ppk_p->len=htons(TCP_HEADER);

	memcpy(checkbuff+PSEUDO_HEADER, &syn.tcp,
        	TCP_HEADER+PSEUDO_HEADER);
        syn.tcp.check=in_cksum((unsigned short*)checkbuff,
                        PSEUDO_HEADER+TCP_HEADER);

        syn.ip.ihl=5;
        syn.ip.version=4;
        syn.ip.tos=0;
        syn.ip.tot_len=htons(IP_HEADER+TCP_HEADER);
        syn.ip.frag_off=0;
        syn.ip.ttl=64;
        syn.ip.protocol=IPPROTO_TCP;
        syn.ip.saddr=localip;
        syn.ip.daddr=remoteip;
	syn.ip.check=in_cksum((unsigned short*)&syn.ip, IP_HEADER);

	memset(&sin, 0, sizeof(sin));
        sin.sin_family=AF_INET;
        sin.sin_port=port;
        sin.sin_addr.s_addr=remoteip;

        shoot=sendto(sp_fd, &syn, IP_HEADER+TCP_HEADER,
        	0, (struct sockaddr *)&sin, sizeof(sin));
        if(shoot<0)printf("SP_ERROR\n");
}

/* gcd functions from nmap by fyodor . sorry if not his own :) */
unsigned long euclid_gcd(unsigned long a, unsigned long b) {
  if (a < b) return euclid_gcd(b,a);
  if (!b) return a;
  return euclid_gcd(b, a % b);
}
unsigned long get_gcd_n_ulong(int numvalues, unsigned long *values) {
  int gcd;
  int i;

  if (numvalues == 0) return 1;
  gcd = values[0];
  for(i=1; i < numvalues; i++)
    gcd = euclid_gcd(gcd, values[i]);

  return gcd;
}

/* sequence checks slightly modified from fyodor */
void check_incr(void)
{
	int incr_i, i = 0;

	seqs_incr = (0.5)+ seqs_incr / MAXPROBES;
	seqs_sum = 0;
	for(i=0;i!=MAXPROBES-1;i++)
	seqs_sum += pow(DIFF(seqs_diff[i], seqs_incr),2);
	seqs_sum /= MAXPROBES;
	incr_i = (unsigned long)(0.5 + pow(seqs_sum, 0.5));
	if(incr_i < 75) 
		printf(
	"\nMicrosoft ISN Generation ! Who Do You Want To Spoof Today ?\n");
	else printf("\nRandom Incremental Box. Good Luck !\n"); 
}

void seqs_check(void)
{
	int i=0;

	seqs_incr = 0;
	for(;i!=MAXPROBES-1;i++) { 
        	printf(
	"\033[1;34mSEQ%d [\033[1;32m%u\033[1;34m]\tSEQ %d [\033[1;32m%u",
			i,ntohl(seqs[i]),i+1,ntohl(seqs[i+1]));
   		printf(
	"\033[1;34m]\tDIFF [\033[1;32m%lu\033[1;34m]\n", seqs_diff[i]);	
	} 
	seqs_gcd=get_gcd_n_ulong(MAXPROBES, seqs_diff);
	if(seqs_gcd) {
		for(i=0;i!=MAXPROBES;i++) 
			seqs_diff[i] /= seqs_gcd;
		for(i=0;i!=MAXPROBES;i++) {
			if(seqs_diff[i] > 50000000) {
				printf(
		"\nTRULY RANDOM BOX. Back Off That One :O\n");
			break;
			}
		seqs_incr += seqs_diff[i];
		}
	}
	if(seqs_gcd == 0) 
		printf(
	"\nISN CONSTANT ! Suit Yourself As You Like It :)\n");
	else if(seqs_gcd % 64000 == 0)
		printf(
	"\n64K Golden Rule ! Have a Nice Spoofing Day ...\n");
	else if(seqs_gcd % 800 == 0)
		printf(
	"\n800 Increments [64K like] !\n");
	else check_incr();
	printf("\n\033[1;34mSEQ Probing Done.\033[0m\n");
}

int main(int argc, char **argv)
{
	int opt, i=0;
	struct iphdr *ip;
	struct tcphdr *tcp;
	char packet[MTU];

	if (geteuid() || getuid()) {
                printf("Devi essere root ...\n");
                exit(0);
        }
	if (argc<7) {
            printf("\nUso: %s -h host -p porta -i interfaccia\n\n", argv[0]);
            exit(0);
        }

	while ((opt = getopt(argc, argv, "h:p:i:")) != EOF) {
                switch(opt)
                {
			case 'h':
				remoteip=nameResolve(optarg);
				break;

			case 'p':
				port=htons(atoi(optarg));
				break;

                        case 'i':
                                IF_NAME=optarg;
                                if(strstr(IF_NAME, "eth")) IF_LEN=14;
                                else if(strstr(IF_NAME, "ppp")) IF_LEN=0;
                                else {
                                        printf("solo eth|ppp.\n");
                                        exit(0);
                                }
                                break;
                        default:
                                printf("Unknown Option.\n");
                                exit(0);
                                break;
                }
        }			

	raw();
	iflink=tap(IF_NAME, 1);

	printf("\n\033[1;32mSEQ PROBE\033[0m");
        printf("\n\033[1;34mISN Generation Prober by FuSyS\033[0m");
        printf("\n\033[1;34m[S0ftPj | BFi]\033[0m\n\n");
	printf("\033[1;34mLocal  IP: \033[1;32m%s\033[0m\t", ntoa(localip));
	printf("\033[1;34mRemote IP: \033[1;32m%s\033[0m\n\n", ntoa(remoteip));

        ip = (struct iphdr *)(((char *)packet)+IF_LEN);
        tcp = (struct tcphdr *)(((char *)packet)+(sizeof(struct iphdr)+
                                        IF_LEN));
        memset(&packet, 0, sizeof(packet));
	memset(&seqs, 0, sizeof(seqs));
	memset(&seqs_diff, 0, sizeof(seqs_diff));

        for(;i!=MAXPROBES;i++) { 
                fire_syn(htons(INITSOURCE+i), htonl(INITSEQ+i));
                while(recv(iflink, &packet, sizeof(packet), 0)) {
                        if(ip->protocol == IPPROTO_TCP) {
                                if(ip->saddr == remoteip &&
                                        ip->daddr == localip) {
					if(tcp->source == port &&
					tcp->dest==htons(INITSOURCE+i) &&
					tcp->syn && tcp->ack) {
                                        	seqs[i] = tcp->seq;
						if(i>0)
						seqs_diff[i-1] = 
				DIFF(ntohl(seqs[i]), ntohl(seqs[i-1])); 
						break;
                                	}
                        	}
			}
		}
	}
	seqs_check();

	iflink=tap(IF_NAME, 0);
	exit(0);
}
---------- snip ----------

Considerazioni: NON serve in questo caso mettere l'interfaccia in
modalita' promiscua. Ma puo' essere molto utile, per specificare un indirizzo 
IP sorgente spoofato in modo da poter occultare la nostra scansione. Ovvio
che dobbiamo trovarci sul route o sulla LAN o non vedremo i risultati
della scansione...

In questa versione non esiste timeout :) e sapete perche'? Perche' voglio
che contemporaneamente guardiate in un'altra consolle l'output di tcpdump
e comprendiate quindi da soli cos'e' che non va. Soprattutto anche il
comportamento del kernel in risposta all'host remoto.

Ricordate che pow() abbisogna della libreria matematica. Quindi linkate
con -lm

------[ I G N O R A R E  G L I  I G N A R I ]------

Perche' impedire all'host che spoofiamo di inviare i suoi RST? Semplice.
Se manda i suoi RST prima che noi abbiamo completato il 3way, l'attacco
fallira' miseramente. Se lo stack del nostro bersaglio accoglie i RST senza
vagliare i numeri di sequenza in gioco, fallira' anche nonostante sia
stato completato il 3way. Certo, possiamo scegliere IP non assegnati ad
alcuna macchina. Ma spesso lo SP00FiNG ci servira' per bypassare
restrizioni ed autenticazioni basate su IP (argh! :O non basate mai la
vostra sicurezza sul solo IP). In questo caso usare IP 'inesistenti' non
ha senso, a meno che non sia sufficiente far parte di una certa classe di
indirizzi.

Il sistema piu' utilizzato e' sicuramente la tempesta/marea di SYN, o Syn
Flood. DoS vecchio come il cucco, ha trovato pubblica notorieta', al
solito, grazie a daemon9 ed al suo progetto Neptune. Come funziona questo
attacco DoS?

Ogni stack TCP/IP alloca della memoria necessaria a strutture che
identificano la connessione in corso. Se non ci fosse un limite alle
connessioni ed alle strutture allocabili, basterebbe iniziare qualche
centinaia/migliaia di connessioni per esaurire tutta la memoria di lavoro
del sistema e fargli mangiare la polvere. Fortunatamente esiste quello che
viene chiamato backlog.

Il backlog specifica quante connessioni non completate o non ancora
prelevate con accept() possano rimanere in sospeso, allocando memoria.
Ogni connessione che trovi il backlog 'occupato' verra' silenziosamente
scartata dal kernel.

Quindi se noi affoghiamo di richieste di connessione una porta TCP di un
sistema otterremo di riempire il backlog, bloccando con richieste pendenti
ogni altro segmento TCP. Inoltre il sistema rispondera' con una sequela
continua di SEQ/ACK ignorando ogni successiva richiesta a quella porta,
che sara' cosi' 'silente'.

Come ho gia' detto questo non e' il solo modo. Ha pero' la fortuna di
essere quasi sempre occulto. Sono infatti pochi i sistemi che logghino
ogni tipo di scansione semi aperta come quella mediante sole SYN. D'altra
parte c'e' da dire che molti OS cominciano ad essere protetti da questo
tipo di DoS, proprio per gli effetti dannosi che il tool di daemon9 ha
apportato a causa dei vari script kid. Ad esempio linux implementa il
concetto dei SYN cookies per ripararsi dal DoS, fornendo un protocollo
criptografico di autenticazione per gli utenti legittimi, permettendo loro
di connettersi anche a backlog saturo.

Ovviamente, l'host che spoofiamo puo' anche essere down, offline o spento.
Come e quando, puo' ogni tanto essere 'implementato'. A mio modo di
vedere, e' meglio aspettare che un host sia down, piuttosto che entrare in
una silenziosa guerra a colpi di DoS per intasare le code del sistema
spoofato. Oppure, meglio ancora, usare IP inesistenti :)

------[ L I N U X  B L I N D  S P 0 0 F i N G ]------

Ho detto che linux si inserisce negli host praticamente impossibili da
attaccare mediante queste tecniche. Ebbene, non e' del tutto vero. Esiste
una buona parte di macchine linux che sono decisamente vulnerabili allo
SP00FiNG cieco. Precisamente TUTTE le box linux con kernel inferiore al
2.0.36 !!! Questo e' forse l'esempio piu' lampante di falsa sicurezza. Da
quando linux e' dotato di un generatore random di ISN, ogni sysadmin sulla
terra si e' probabilmente sentito al sicuro dallo spoof. Ebbene esiste un
modo, scoperto il 5 ottobre 1998, che permette di bypassare totalmente il
controllo operato dal kernel sull'ACK del client. Questo baco e' stato
corretto a partire dal kernel 2.0.36, ma siccome e' stato reso pubblico
solo di recente, non sembrano esserci state ondate pubbliche di attacchi.
Non sono usciti codici pubblici per avvantaggiarsi di questa situazione.
Di certo, pero', esistono ancora MOLTE macchine linux con kernel <=2.0.35
in giro per InterNet. Questo vuol dire che abbiamo una ulteriore
possibilita' di attaccare macchine che probabilmente sono considerate
molto sicure da questo punto di vista.

Questo baco in realta' permette NON di spoofare realmente una connessione
TCP portando a termine l'handshake 3way prevedendo il SEQ del server,
bensi' passando dati alla applicazione PRIMA che sia stato completato il
3way stesso, e quindi senza che si debba controllare l'ACK del client.

Questo baco e' il risultato di tre problemi fondamentali. Per prima cosa
il kernel esegue un controllo sul numero di accetazione del client solo se
il pacchetto dispone della flag ACK. Secondo, il kernel inserisce i dati
ricevuti in una coda, prima del completamento del 3way, ma cmq dopo che il
SYN del client sia stato accettato dal server. Infine copia i dati dalla
coda all'applicazione se riceve un pacchetto contenente flag FIN anche se
la connessione non e' mai stata stabilita e non si e' mai avuto passaggio
di stato a ESTABLISHED.

In questo modo, quello che va fatto e':

- inviare un pacchetto con flag SYN per iniziare la connessione e far
  passare il socket remoto in SYN_RCVD
- inviare i dati in un pacchetto senza flag ACK [cosa normalmente non
  possibile in stack corretti che non accettano dati senza ACK, tranne che
  nel SYN iniziale]
- concludere mediante invio di pacchetto con flag FIN che portera' lo stato
  su CLOSE_WAIT e copiando i dati all'applicazione.

(...)

E' giunto il momento di tentare qualcosa di pratico, giusto per testare un
attimo questa nuova conoscenza. Mi spiace ma non ho intenzione di
rilasciare come pubblico un tool robusto di SP00FiNG cieco capace di
attaccare ogni tipo di server TCP mediante inserimento interattivo di
comandi. Quello lo lascero' per me :)

Vi propongo invece qualcosa di simpatico e, comunque, decisamente di black
magic rispetto alla maggior parte dei tool circolanti :) con lo stesso
obiettivo. Un codice per inviare email fake. Badate bene, questo consente
davvero di occultarsi, potendo spoofare l'IP. Infatti nei vari header
Received: tipici di ogni transazione SMTP potremmo far apparire un innocuo
nowhere.net [1.1.1.1] :) o magari usare IP non assegnati nel dominio della
walt-disney associandoli a sexy-mickey.disney.com :P oppure usando reali
IP; in questo caso pero' dovrete far fronte voi al problema dei RST remoti
dal vero IP.

------[ L A  F A K E  M A I L  D E F I N I T I V A ]------

Il codice che ho preparato lavora contro tre tipi di server. Quelli che
operano ancora con la regola dei 64k, quelli basati su incremento
Microsoft ed infine i linux vulnerabili <=2.0.35.

Ecco un tipico esempio di sessione:

SMAIL
iP SP00FiNG Mailer by FuSyS
[S0ftPj | BFi]

Local  IP: 212.XXX.XX.XXX Remote IP: 193.XXX.XX.XX

Probing host for ISN generation ...
Target is 64k ruled !
SYN Packet Fired ...
Last ISN is 1488448000 . Guessed ACK is 1488512001
ACKs Fired. Connection Hopefully Established.
Firing Packet !!!
Done. RSTing the connection ...

E nell'header della email che ho ricevuto appariva :PPPP :

Received: from nowhere.net ([1.20.3.40]) by xxxxx.xxxx.xxx via SMTP

Ora provate voi a fare un bel traceroute su quell' IP :) chissa' che
succedera' ?! :) Davvero un nowhere.net ...

In questa versione viene ancora utilizzato un data file che contiene il
testo della transazione SMTP da spoofare. Ma rilascero' una versione che
permetta l'uso come se si trattasse di mail(1) =:)

Questo codice verra' mostrato, insieme a xTHOT, ad HackIt99 da qualcuno di
S0ftPj, se non da me stesso. In realta' sono ormai pronti, ma non ho avuto
sufficiente tempo di debug a causa di svariati impegni extra-hack :)

D'altra parte avete la possibilita' di tentare qualcosa da farmi vedere.
Tutto sommato e' presente ogni cosa vi serva negli altri miei codici e
scritti relativi a TCP/IP. Si tratta solo di fare un collage di idee ed
implementazioni.

Cosa vi serve?

- un socket di tipo RAW.

- un resolver [non indispensabile, ma comodo].

- una routine di basso livello per creare pacchetti TCP. 
  Questa puo' essere codata mediante le facili strutture di ~include/netinet
  oppure mediante buffer da riempire con un puntatore, byte dopo byte,
  come nel mio forger Orodruin.

- una routine per leggere direttamente dal livello datalink mediante
  SOCK_PACKET, che seppur deprecato nei log del kernel :) e' comunque
  ancora usato anche nella libpcap.

- un meccanismo veloce come SEQPROBE per rilevare i numeri di sequenza.

- indovinare il prossimo numero e sparare i dati con l'ACK apposito [non
  con i linux <=2.0.35]

Come indovinare il numero di sequenza corretto? Beh, per la regola dei
64000 non ci resta che sommare 64k al SEQ che abbiamo ottenuto dalla
sonda, eventualmente, nel caso di server occupati, possiamo decidere di
inviare un numero maggiore di pacchetti considerando anche eventuali
rallentamenti lungo il route o magari altre connessioni da parte di altri
host.

Nel caso di sistemi incrementali Microsoft, potete facilmente vedere come
questo numero aumenti di poche unita' ogni tot secondi. Questo e'
abbastanza facile da spoofare quindi. Bastera' inviare una serie di
pacchetti che contenga incrementi del nostro ACK sufficienti a coprire
l'arco di tempo incrementale usato dal server, qualunque esso sia.

Per linux vulnerabili NON dobbiamo neanche preoccuparcene. Basta agire nel
modo suddetto in precedenza, giocando quindi con le transizioni di stato
TCP mediante le flag SYN e FIN.

Quello che spesso disorienta la maggior parte delle persone, anche alcune
tra i cosiddetti esperti di sicurezza, e' la natura full duplex delle
connessioni TCP. Quello che ci interessa e' solo indovinare l'ACK giusto.
Questo portera' lo stato su ESTABLISHED. A questo punto non ci interessa
assolutamente inviare ACK relativi ai dati trasmessi dal server. Non
pensateci neanche. Semplicemente inviate i vostri dati.

Cosa succedera' a questo punto? Lo stack remoto passera' i nostri dati
all'applicazione ed inviera' le risposte del caso. Risposte che noi non
saremo in grado di vedere e riconoscere quindi. Anche se fossimo in grado
di prevederle eventuali nostre risposte errate darebbero il via ad una
serie di flussi di ACK che renderebbero il nostro attacco individuabile.
In mancanza dei nostri ACK lo stack remoto pensera' semplicemente che i
suoi pacchetti siano andati perduti e ritrasmettera' fino al timeout.
Intanto i nostri comandi saranno gia' stati processati a livello utente.

Quindi la cosa importante e' giungere al corretto ACK. Nel caso di
pacchetti multipli, e' importante non iniziare subito con valori che
riteniamo prossimi a quello giusto. Se infatti il server remoto ricevesse
un nostro ACK maggiore di quello atteso, risponderebbe con un RST. E'
quindi decisamente meglio partire da valori inferiori andando a salire.
Questo NON provoca invio di RST, almeno fino a quando non si supera il
valore atteso. Esistono alcuni sistemi operativi che inviano comunque RST,
ma sono una eccezione.

Interessante e' notare che questi pacchetti con flag RST non influenzino
minimamente il nostro attacco. Come mai?

Secondo l'RFC793 esistono delle regole ben precise per discriminare
connessioni legali, aborti, generazioni di numeri di sequenza e riscontro
di anomalie nella trasmissione. In particolare viene evidenziato che:

- segmenti contenenti la flag RST debbano essere inviati, fra l'altro, in
  situazioni desincronizzate come SYN_SENT e SYN_RECV nel caso il segmento
  in ingresso riconosca mediante un ACK dati non ancora inviati [ovvero se
  sia un ACK inaccettabile].

- in situazioni non espressamente esaminate come la suddetta non deve
  essere inviato un segmento RST bensi' devono essere usati algoritmi
  precisi di tipo diagnostico, che facciano uso di timeout e ritrasmissione 
  per valutare la anomalia.

- un ACK accettabile e' compreso nella seguente disuguaglianza:

		SND.UNA < SEG.ACK =< SND.NXT

  dove SEG.ACK e' il numero di sequenza atteso nel segmento in arrivo,
       SND.UNA e' il piu' vecchio SEQ riconosciuto da un ACK e
       SND.NXT e' il prossimo numero di sequenza da inviare.

Si capisce quindi come prevedendo un numero maggiore di quello attesso
dall'host remoto, non faremmo altro che provocare l'invio di un RST.
utilizzando invece un ACK minore non effettueremo la transizione ad
ESTABLISHED, ma d'altra parte non avremo RST vaganti che possano
insospettire eventuali logger dell'host remoto o dell'host spoofato.

Comunque questi RST poco interessano l'efficacia del nostro attacco.
Servono solo a TCP per impedire connessioni che siano ritenute vecchie,
concluse o abortite. In pratica per impedire duplicati di connessioni
preesistenti. 

Ma non appena l'host ricevera' il nostro ACK corretto passera' lo stato in
ESTABLISHED e potremo inviare dati all'applicazione senza problemi, per
poi chiudere la connessione mediante half-close con FIN o aborto con RST.

Questo e' lo scheletro teorico dell'attacco. Il tool disponibile a breve
ad HackIt99 e sul nostro sito all'URL: http://www.s0ftpj.org
implementera' questo tipo di tecniche.

------[ C O N C L U S I O N E ]------

Con questo il progetto 0N0S3NDAi e' concluso. Sinceramente al momento non
esistono in italiano guide di questo spessore sull'iP SP00FiNG. Come vi
avevo detto, non c'e' comunque tutto. D'altronde i concetti esposti sono
validi per ogni tipo di attacco od implementazione che tiri in ballo lo
spoof degli indirizzi IP. Questa guida sara' disponibile sul sito di
S0ftPj in un blocco unico, comprendente entrambi i capitoli, i tool ed
eventualmente anche nuovi codici, soluzioni ed idee.

[DOCUMENTAZIONE IN INGLESE]----------------------------------------------
|									|	
|	Libri:		W.R.Stevens TCP/IP Illustrated Vol.1,2		|
|			W.R.Stevens UNIX Network Programming 2ed Vol.1	|
|									|
|	  RFC:		768, 791, 792, 793, 1071, 1282, 1323, 1379, 	|
|			1600, 1644, 1948				|
|									|
|	 txts:		IP-spoofing Demystified da PHRACK48		|
|									|
-------------------------------------------------------------------------

OLAs :) to:
		 smaster, \sPIRIT\, |scacco|, bELFaghor, pIGpEN, B_Berry
		 Tw0lf, xmulder, Nell0z, CavaLLo dC, DreadN e tutti i
		 componenti di S0ftPj e dell'Orda delle BadLands

FuSyS

--------------------[ previous ]---[ index ]---[ next ]---------------------
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
==============================================================================