Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

GET/POST numerici

Come eseguire controlli di dati numerici inviati all'applicazione via POST o GET
Come eseguire controlli di dati numerici inviati all'applicazione via POST o GET
Link copiato negli appunti

Introduzione

Nelle query del tipo seguente, eseguite lato server dall'applicazione PHP:

$sql="SELECT id_documento, user_id FROM tabella_upload WHERE user_id=".$_GET['userid'];

è necessario controllare che la variabile passata in GET (identicamente vale per POST) sia realmente un numero. Pensiamo infatti al caso in cui per varie ragioni siano noti i nomi delle tabelle del database e lo userid passato in query string sia:

60 AND 0 UNION SELECT usr, pwd FROM tabella_utenti.

La query risuta:

SELECT id_documento, user_id FROM tabella_upload
WHERE user_id=60 AND 0
UNION SELECT usr, pwd FROM tabella_utenti

Se a questo punto l'applicazione prevede un output per tali dati (troveremo i valori di usr che corrisponderanno alla colonna id_documento, e pwd a user_id), il cracker ha la lista completa di login e password degli utenti. Vengono estratti solamente i dati soddisfacenti alla seconda SELECT, in quanto la condizione AND 0 rende sempre falsa la prima.

Ciò che il cracker vede è la lista del contenuto della base dati, formattato secondo quanto definito dal progettista dell'applicazione. Ad esempio: la lista di nomi utente affiancati a pulsanti "Aggiungi al carrello", se si tratta di acquisti online. Ovviamente poco importa la "strana" rappresentazione grafica risultante, ma il contenuto.

Di qui, se la lista è in chiaro, il disastro è completo; se la password è stata invece "hashata" con un md5(), ad esempio, può essere possibile che con un attacco di brute force si riesca comunque ad evincere un login valido. È bene ribadire che più corta e "debole" è una password, più facile è che l'attacco brute force abbia successo.

Per debole si intende un password "corta" e/o composta di caratteri, magari solamente minuscoli, o numeri: [a-z]+[0-9], oppure addirittura consistente in una parola di senso compiuto ricavabile da un comune dizionario.

Di male in peggio: riferendoci sempre alla query sopra, pensiamo cosa può succedere se, in determinati casi, il cracker attribuisce a user_id la stringa:

60 AND 0; DROP table qualsiasi_tabella.

La query diviene:

SELECT id_documento, user_id FROM tabella_upload WHERE user_id=60 AND 0;
DROP table qualsiasi_tabella

e ci siamo giocati un'intera tabella (Requiescat In Pacem). Va detto però che in genere query multiple non possono essere eseguite, almeno di non usare comandi appositi e ben definiti, cioè a meno che lo stesso programmatore non preveda tale possibilità tramite codice.

GET/POST numerici con query ad "*" o a più colonne

Nel caso di query del tipo seguente:

$sql="SELECT * FROM tabella_upload WHERE user_id=".$_GET['userid'];

poiché UNION implica che il numero di campi estratti dalle due query sia il medesimo, conoscendo la struttura interna della tabella del db o per tentativi ed errori, costruiamo quindi:

SELECT * FROM tabella_upload WHERE user_id=60 AND 0
UNION SELECT usr, pwd, 0, 0, 0, 0, 0 FROM tabella_utenti

nel caso in cui i campi di tabella_upload siano ad esempio 7.

Il risultato è quello sperato (dal cracker, non dall'amministratore dell'applicazione..):

marco

e887a115f99cb3a3d01baf63d0ddc682

 

 

 

 

 

monica

7cf706b9c0a54bc05e6ac6baea77d59c

 

 

 

 

 

Rimedio per exploit basati su query con dati numerici

Evitare tali exploit è facilissimo: risulta sufficiente eseguire un controllo sul dato passato e forzarlo ad essere di tipo numerico:

$sql="SELECT id_documento, user_id FROM tabella_upload
      WHERE user_id=".(int)$_GET['userid'];

In caso di tentativo di cracking, al limite il valore della variabile GET/POST sarà nullo o comunque numerico e non verranno eseguite query arbitrarie. Se alla nostra query vengono passati dati che ci aspettiamo essere solamente numerici, quindi, è strettamente necessario operare un "type casting" su di essi.

Infine, poiché, per nostra fortuna, PHP non dà indicazioni sui nomi delle tabelle, né durante il suo normale funzionamento né in caso di errore standard, questo tipo di attacco è effettivamente efficace se i nomi delle tabelle sono i soliti noti nomi banali oppure se l'applicazione è open source. Oppure ancora se si riesce ad ottenerli per altra via, sfruttando altri exploit esistenti o comunque messaggi d'errore provocati ad hoc da "esperti".

Annotazione

Al riguardo delle sempre possibili collisioni dell'MD5, se (giustamente) paranoici, si può usare l'algoritmo SHA oppure una qualche combinazione più sicura dell'MD5, quale, ad esempio:

md5(md5($password.$stringa_particolare_nota_alle_parti)).

L'hash in uscita dall'algoritmo SHA1 è più lungo, quindi più sicuro.


Ti consigliamo anche