Anatomia di un Exploit

Esistono due approcci all’hacking: il primo, che possiamo definire tattico, si basa sulle opportunità che possono derivare da problemi strutturali o da configurazioni deboli. Il secondo approccio è quello dell’attacco alla vulnerabilità. Una vulnerabilità viene scoperta e per un certo periodo di tempo il sistema rimane vulnerabile a questo attacco. Se non esistono policy di aggiornamento il bug rimane presente anche se il rimedio è disponibile.

I due scenari si possono sovrapporre: può accadere che alcuni sistemi non possano essere aggiornati perché l’aggiornamento andrebbe a compromettere altre funzionalità (come per esempio un software proprietario).

Nel secondo di questi scenari, ovvero quello dell’attacco basato sulla vulnerabilità esiste un elemento cardine: l’exploit.
L’exploit è lo strumento, l’arma digitale che permette di sfruttare la vulnerabilità e quindi ottenere l’accesso remoto o l’accesso a risorse e dati riservati.

Esistono vulnerabilità di diversa natura e naturalmente adeguati metodi per sfruttare queste vulnerabilità. Quindi sia che si parli di SQL injection, sia che si parli di buffer overflow si parlerà anche di exploit: ma exploit è una parola neutra che va riempita di contenuti, visto che la stessa parola designa nature completamente diverse.

Per cercare di capire meglio cos’è un exploit prendiamo come esempio il “principe” di questa categoria di software: il buffer overflow.
In questo articolo, illustrando in maniera molto superficiale il funzionamento di un exploit per buffer overflow, cerco di mettere in risalto gli elementi che permettono di capire cos’è genericamente un exploit, termine univoco dietro al quale si nasconde una molteplicità di software di natura assai diversa. Per quanto possibile ho evitato eccessivi tecnicismi, misura che forse comunque potrebbe non bastare per rendere comprensibili alcuni passaggi che necessitano di una minima conoscenza del funzionamento di un programma e di un microprocessore.

Buffer Overflow

Il Buffer Overflow è una vulnerabilità originata da un errore di programmazione. In alcuni casi può consentire all’hacker di introdurre da remoto codice macchina e sovvertire il normale funzionamento di un software, permettendo all’hacker stesso di ottenere il controllo del computer senza la necessità di autenticarsi con password o altri metodi.

Il Buffer Overflow è una condizione che si viene a realizzare quando in un’area di memoria temporanea (buffer) di determinate dimensioni, vengono introdotti più byte di quelli previsti causando lo “straripamento”  di dati al di fuori del buffer stesso. Se lo straripamento viene effettuato con dati casuali probabilmente si otterrà un crash del software vulnerabile (causando una condizione di denial of service, attacco DoS); se invece i dati saranno preparati ad arte l’hacker sarà in grado di far fare all programma quello che vuole, come aprire una shell su una porta Tcp specifica e quindi collegarsi da remoto, o aggiungere un utente al sistema.

Un buffer overflow classico agisce sulla memoria stack. La memoria stack è una particolare zona di memoria che i sistemi operativi utilizzano per esempio per effettuare la chiamata a funzioni. Una funzione è una procedura che necessita parametri e può essere chiamata in diversi punti di un programma. Quando un programma invoca una funzione passa i parametri nello stack e quindi trasferisce il controllo all’indirizzo della funzione.
Qui entra in gioco il buffer overflow: se il parametro passato è di dimensioni superiori a quelle previste dal programmatore, si crea una condizione favorevole all’hacker; se inoltre il parametro è in qualche modo controllabile da remoto l’hacker può introdurre in questo buffer codice macchina.
Così è chiaro come introdurre il codice macchina: ma come si trasferisce il controllo a questo codice? Per capirlo dobbiamo tornare a dare uno sguardo all memoria stack di cui parlavo prima.

Abbiamo visto che il programma che usa una funzione passa i parametri nello stack e quindi trasferisce il controllo alla funzione stessa. Cosa significa trasferisce il controllo?
Le funzioni sono immagazinate nella memoria centrale ed hanno un indirizzo numerico: trasferire il controllo significa che la CPU mette in un particolare registro detto Instruction Pointer (EIP nei processori Intel) l’indirizzo della funzione. Ma quando la funzione ha completato il proprio lavoro, come torna al programma chiamante? Semplice: all’atto della chiamata l’indirizzo dell’istruzione del programma chiamante viene memorizzata nello stack: alla fine dell’esecuzione della funzione il sistema preleva dallo stack questo indirizzo e gli trasferisce il controllo.
Però l’hacker inviando più dati di quelli previsti passa i limiti del buffer, riuscendo così a sovrascrivere anche l’indirizzo di ritorno! Così alla fine dell’esecuzione la funzione preleverà dallo stack l’indirizzo per tornare al programma chiamante, ma in realtà troverà l’indirizzo messo dall’hacker, indirizzo che punterà a istruzioni in codice macchina inserite dall’hacker: il cerchio si chiude.

Il Payload

Se il buffer overflow è il come, bisogna decidere cosa fare una volta preso il controllo del sistema. Il cosa è il payload, ovvero l’insieme di istruzioni inserite dall’hacker. In un attacco buffer overflow il payload è un insieme di codici macchina in grado di eseguire compiti specifici. Questo insieme di codici, un vero e proprio mini-programma si chiamashellcode.

Lo shellcode deve il suo nome al fatto che in origine questo payload serviva per consegnare una shell di comandi all’hacker. Sui sistemi Unix la shellcode eseguiva l’interprete sh con i privilegi del software attaccato. Se il software attaccato girava con privilegi root, la shell era una rootshell, con poteri assoluti.

Nel tempo gli shellcode si sono evoluti. Oltre all’esecuzione di codice hanno dovuto implementare tecniche di evasione dagli IDS (Intrusion Detection System), in modo da camuffarsi e non essere riconosciuti come elementi nocivi.

Le shellcode più classiche aprono una linea di comando su una porta Tcp, oppure aprono un back-channel verso il computer dell’hacker per aggirare le regole del firewall. Esistono shellcode che aggiungono un utente al sistema, consentendo all’hacker di loggarsi comodamente come un utente normale (magari con privilegi di amministratore).

Se l’exploit può essere scritto in qualsiasi linguaggio (C, Python, Ruby…) la shellcode deve essere per forza codice macchina. Normalmente in un listato la shellcode prende l’aspetto di una sequenza di numeri esadecimali. Sequenza che non è altro che puro codice macchina.
Il fatto che la shellcode debba essere scritta in linguaggio macchina, perché deve interagire a bassissimo livello con il sistema, rende assai difficoltosa la creazione di questi codici. Quella dello shellcoding può essere considerata un’arte e meriterebbe una trattazione approfondita a parte.

Conclusione

Spesso chi ha a che fare con l’hacking si imbatte nel termine exploit. Exploit è un nome generico che si da a codici che possono avere una natura molto diversa tra loro: un exploit che sfrutta unaSQL injection sarà diversissimo da un exploit per buffer overflow.
In genere però tutti gli exploit condividono due elementi: un “come fare”, e un “cosa fare”. Il come fare fa riferimento alla vulnerabilità stessa e su come sfruttarla; il “cosa fare” è l’elemento denominatopayload, le azioni da compiere una volta che si sia riusciti ad sfruttare la falla. In un buffer overflow il payload sarà una shellcode in codice macchina che esegue comandi inseriti dall’hacker per ottenere il controllo del sistema.
Essendo la shellcode scritta in codice macchina, funzionerà solo e soltanto su un particolare microprocessore, su un particolare sistema operativo o addirittura una particolare versione del sistema operativo. Questo evidenzia il fatto che scrivere un exploit per bufferoverflow funzionante nel mondo reale (e non solo in laboratorio) che sfugga anche ai controlli di IDS sia un compito tutt’altro che banale.

5 comments to “Anatomia di un Exploit”
  1. Pingback: Introduzione a Metasploit | PillolHacking.Net

  2. Pingback: Pillolhacking.Net: I Migliori Articoli del 2008 | PillolHacking.Net

  3. Pingback: Gli 8 Errori più Pericolosi Commessi dai Web Developers | PillolHacking.Net

Comments are closed.