Archivi tag: exploit

Cisco PIX 501 ed il fingerprint SSH (non visualizzabile da CLI)

Qualche tempo fa, mentre provavo ad abilitare l’SSH sul mio PIX 501, ho cercato di visualizzare il fingerprint che viene generato dopo aver creato la coppia di chiavi RSA pubblica/privata.

pix 501,sshv1,sshv2,rsa1,rsa2,exploit,ssh 1.5,fingerprint,chiave pubblica,chiave privata

Con mio enorme stupore, dopo una breve ricerca su Internet e diversi tentativi da console, ho constatato che tale fingerprint non è visualizzabile direttamente dalla CLI del PIX.

L’unico comando presente da linea di comando è il seguente:

NightFirewall# sh ca mypubkey rsa

che consente di visualizzare la chiave pubblica usata dal firewall in questione, ma non il suo fingerprint.

Inoltre, dando un’occhiata al file .ssh/known_host presente nella mia home, ho notato che il fingerprint salvato è diverso da quelli associati agli host SSHv2. Questo a mio avviso è imputabile a due fattori:

1) L’uso di RSA1 anzichè RSA2 per la generazione del fingerprint stesso;

2) La versione del protocollo SSH utilizzata dal firewall (ovvero la 1.5).

Un modo per visualizzare il fingerprint del PIX 501 però esiste, e si basa su nmap:

nightfly@nightbox:~$ sudo nmap -sS -A <IP PIX 501>

Starting Nmap 5.00 ( http://nmap.org ) at 2011-09-05 20:30 CEST
Interesting ports on *.*.*.*:
Not shown: 998 closed ports
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      Cisco SSH 1.25 (protocol 1.5)
|_ ssh-hostkey: 1024 **:**:**:**:6f:62:05:dd:a6:3b:43:1f:**:**:**:** (RSA1)

Mistero svelato.

PS: i lameri che volessero fare dei tentativi di exploit verso la mia macchina (poichè l’SSH 1.5 è palesemente vulnerabile), sappiano che tale servizio non è pubblicato all’esterno ed accetta connessioni solo da determinati host della rete interna. Ergo abbandonate qualunque idea bellicosa.

A presto.

rkhunter ed il rootkit Xzibit

Qualche giorno fa sono rientrato dalle mie meritate ferie (che poi tanto ferie non erano) e mi sono ritrovato con uno un reverse proxy dell’ambiente di test spento.

Ho chiesto ai miei colleghi il perchè di questa cosa e mi è stato detto che proprio su quel proxy era stata pubblicata la porta 25 (SMTP) ed avevano paura che fosse stato ownato. Non chiedetemi per quale motivo è stato fatto questo accrocchio, ma qui i problemi erano altri, ovvero:

1) Essendo il reverse proxy basato su una distro che non viene aggiornata da illo tempore, c’era un’ampia probabilità (diventata certezza dopo ulteriore analisi) che il demone SMTP fosse bacato;

2) La porta 25 è stata lasciata in forwarding per circa una settimana, il che ha aumentato in modo esponenziale il rischio che la macchina venisse ownata da qualche lamer di turno.

rkhunter

Armato dunque di molta pazienza riaccendo la macchina ed effettuo una prima scansione con chkrootkit, che però non segnala nulla di anomalo. Non contento installo anche rkhunter (il cui rpm lo potete scaricare da qui), il quale, alla fine dell’analisi, mi riporta il seguente sommario all’interno del file di log:

[10:10:09] System checks summary
[10:10:09] =====================
[10:10:09]
[10:10:09] File properties checks...
[10:10:09] Required commands check failed
[10:10:09] Files checked: 141
[10:10:09] Suspect files: 6
[10:10:09]
[10:10:09] Rootkit checks...
[10:10:09] Rootkits checked : 253
[10:10:10] Possible rootkits: 1
[10:10:10] Rootkit names    : Xzibit Rootkit
[10:10:10]
[10:10:10] Applications checks...
[10:10:10] Applications checked: 7
[10:10:10] Suspect applications: 4
[10:10:10]
[10:10:10] The system checks took: 13 minutes and 25 seconds
[10:10:10]
[10:10:10] Info: End date is Wed Aug 31 10:10:10 CEST 2011

Uhm, possibile che sia stato installato il rootkit Xzibit? Spulcio ulteriormente il log, alla ricerca del file che ha fatto scattare l’allarme. Il risultato è il seguente:

Found string 'hdparm' in file '/etc/rc.d/init.d/vmware-tools'. Possible rootkit: Xzibit Rootkit

Ebbene, rkhunter ha interpretato come “sospetta” la stringa hdparm presente nei wmware-tools. Ma essendo una macchina virtuale è palese che si tratta di un falso positivo.

Dunque se la vostra macchina è virtuale e ci avete installato i wmware-tools è molto probabile che rkhunter generi questo allarme.

Stay tuned.

PS: per la cronaca, il reverse proxy è ok (o almeno così sembra).

DVL (Damn Vulnerable Linux) la distro più vulnerabile che esista

Ormai è risaputo di quanto siano sicure alcune distribuzioni *nix, tra cui la celeberrima FreeBSD (un solo exploit da remoto in 10 anni). Eppure vi sono tante altre distribuzioni che non fanno della sicurezza il loro obiettivo primario. Tra queste vi è certamente DVL (Damn Vulnerable Linux – un nome una garanzia), appositamente forgiata per presentare numerosissime falle di sicurezza ed aiutare gli aspiranti “security consultant” durante la loro formazione. Effettivamente l’idea non è male, in quanto tale distribuzione potrebbe anche essere utilizzata come passatempo, per “testare” l’effetto dei vari exploit sui bug presenti.

Ovviamente trattasi di bug arcinoti e piuttosto datati, per cui le ultime versioni dei software dovrebbero esserne immuni (almeno spero). Comunque, bando alle ciance ed enjoy: http://www.damnvulnerablelinux.org/

Buffer overflow e stack overflow

Un buffer non è altro che una sequenza di lunghezza predefinita di celle di memoria (per semplicità lo si può intendere come un array). Quando si cerca di allocare delle variabili al di fuori dei limiti di tale array si parla proprio di buffer overflow (dove overflow significa straripamento).

Alcuni linguaggi di programmazione (come Java) effettuano un controllo sul corretto utilizzo del buffer, segnalando eventuali anomalie durante la fase di runtime (ovvero durante l’esecuzione del programma). Altri linguaggi invece,  quali C o C++, non operano alcun controllo sulla corretta allocazione delle variabili, che quindi possono essere posizionate in indirizzi di memoria “dedicati” ad altri processi. Sfruttando proprio questa vulnerabilità un utente malevolo potrebbe eseguire del codice arbitrario sul calcolatore della vittima, compromettendone il livello di sicurezza.

Uno degli esempi più diffusi di buffer overflow è lo stack overflow. In particolare, uno stack (che letteralmente significa catasta) è una regione di memoria che viene gestita come una coda LIFO (Last Input – First Output), in cui push (inserimento) e pop (estrazione) sono le uniche operazioni consentite.

Il verificarsi di questo tipo di anomalia è in qualche modo incentivato dal fatto che in moltissime architetture (tra le quali x86), la memoria “cresce” (ovvero viene allocata) in un senso, mentre lo stack viene riempito nel senso opposto. Per focalizzare meglio il problema esaminiamo il seguente codice (scritto in C):

#include <string.h>

void foo (char *bar)
{
char  c[12];

memcpy(c, bar, strlen(bar));  // no bounds checking...
}

int main (int argc, char **argv)
{
foo(argv[1]);

return 0;
}

Questo programmino non fa altro che ricevere da shell una stringa di massimo 12 caratteri (in teoria) e la salva all’interno dello stack dedicato alla funzione foo(). Tale operazione viene effettuata proprio dalla funzione memcpy(), il cui argomento è costituito dalle variabili c (ovvero la stringa), bar e della lunghezza di quest’ultima, calcolata mediante la funzione strlen(). Occorre notare però che memcpy() non effettua alcun controllo relativo ai limiti del buffer, ecco perchè viene usato questo codice come esempio di programma soggetto a stack overflow.

Si focalizzi ora l’attenzione sulla variabile char c[12]. Essa non è altro che un array di 13 posizioni (da 0 a 12) che però può contenere soltanto 12 caratteri, in quanto il linguaggio C aggiunge automaticamente il carattere tappo per indicare la fine della stringa.

Quando vado ad inserire tramite shell la stringa hello, il main() richiamerà la funzione foo() (solo dopo averne preparato il record di attivazione), il cui stack ci apparirà nel seguente modo:

300px-Stack_Overflow_3.png

dove Return Address è l’indirizzo della prossima istruzione da eseguire, Saved Frame Pointer punta alla fine dello stack precedente (ovvero quello della funzione main()), in modo da consentire al programma di risposizionarsi su di esso dopo aver deallocato il record della funzione foo(), e char *bar contiene l’indirizzo della variabile bar (l’asterisco indica che ho a che fare con un puntatore).

Supponiamo ora di andare ad inserire la seguente stringa: “A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​A​x08​x35​xC0​x80”. Lo stack della funzione foo() avrà questa conformazione:

363px-Stack_Overflow_4.png

Come potete notare, il campo dello stack che serviva a restiture il controllo al main() una volta terminata l’esecuzione di foo(), ovvero Saved Frame Pointer, viene sovrascritto, e stessa sorte tocca a Return Address, all’interno del quale viene salvato il seguente indirizzo (in notazione little endian, cioè le cifre più significative sono a destra):

"​x08​x35​xC0​x80"

Questo indirizzo potrebbe puntare ad una locazione di memoria in cui è presente del codice macchina malevolo, e quindi potrebbe consentire ad un eventuale attaccker di ottenere il controllo del sistema remoto.

Esistono comunque diverse tecniche per cercare di prevenire gli attacchi basati su stack overflow. Una di queste (utilizzata nell’ambito dell’architettura SPARC), fa in modo che la memoria e lo stack vengano riempiti seguendo lo stesso verso. In questo modo i “dati in eccesso” non andranno a sovrascrivere alcune delle parti fondamentali dello stack, ma si posizioneranno al di fuori di esso. Tale soluzione però è alquanto “grezza”, poichè potrebbe esserci un altro stack limitrofo a quello considerato, portando a sovrascrivere il suo Saved Frame Pointer oppure il suo Return Address.

Un’altra soluzione consiste nell’usare alcune liberie C e C++ reimplementate (ed a pagamento), le quali, a differenza di quelle standard, garantiscono meccanismi di controllo del buffer.

Si possono usare inoltre delle tecniche per la protezione del puntatore, andando a crittografare mediante un semplice XOR alcuni indirizzi di memoria considerati “sensibili”.

Occorre mensionare anche la tecnica denominata non executable stack. Essa fa in modo che non possa essere eseguito del codice arbitrario (in particolare codice macchina) direttamente dallo stack, basando il suo funzionamento su un bit implementato a livello di CPU, denominato NX (No Execute). In teoria si potrebbe resettare il valore di questo bit impostandolo a 0, anche se nessuno è ancora riuscito a farlo. E’ comunque possibile eludere tale tecnica di protezione seguendo due strade: iniettare il codice macchina in porzioni di memoria non protette (come l’heap), oppure sfruttare dei programmi già allocati in memoria per effettuare chiamate utili all’attacker (ad esempio system(), che consente di eseguire codice arbitrario). Quest’ultima tecnica prende il nome di return-to-libc, in riferimento al fatto che nei sistemi UNIX like, appena un qualunque programma scritto in C viene mandato in esecuzione, la libreria libc automaticamente viene posizionata in memoria.

Ma cosa succede quando l’attaccante non conosce a priori l’indirizzo delle istruzioni malevole da eseguire sull’host remoto? Semplicemente riempie la memoria con una serie di istruzioni no op (ovvero no operation, 0x90 nelle architetture x86), fino ad arrivare all’indirizzo desiderato. Tale tecnica prende il nome di nop sled.

Il post termina qui. A presto.