L'iniezione SQL è possibile con LIMIT?

37

Un mio amico ha creato un'applicazione web che sto testando per divertimento. Ho notato che consente a un utente di impostare il limite di una determinata query e tale limite non è sterilizzato.

Ad esempio, posso scegliere come limite qualsiasi numero o stringa che mi piace. Mi rendo conto che questa è Iniezione SQL , e posso facilmente inserire comandi SQL, ma è davvero possibile estrarre qualsiasi dato o fai qualche danno con un LIMIT ?

Esempio della query:

SELECT * FROM messages WHERE unread = 1 LIMIT **USER INPUT HERE**

Capisco che se l'iniezione fosse nella clausola WHERE avrei potuto facilmente fare un UNION SELECT per estrarre qualsiasi informazione, ma è davvero possibile se l'input dell'utente fosse dopo il limite?

Per ulteriori informazioni, il mio amico utilizza il MySQL DBMS, quindi non è possibile eseguire due query come :

SELECT * FROM messages WHERE unread = 1 LIMIT 10;DROP TABLE messages-- 

Non è possibile.

    
posta Ali 23.12.2014 - 12:04
fonte

6 risposte

73

Puoi creare UNION SELECT qui. L'unico problema è quello di abbinare le colonne ai messaggi, ma puoi indovinare quelli aggiungendo colonne finché non si adatta:

SELECT * FROM messages WHERE unread = 1 LIMIT 
    1 UNION SELECT mail,password,1,1,1 FROM users

Continua ad aggiungere ,1 finché non ottieni il conteggio corretto delle colonne. Inoltre, è necessario abbinare il tipo di colonna. Prova null anziché 1 .

Se riesci a vedere gli errori di MySQL che potrebbero aiutare molto qui. Altrimenti ci provi molto.

Vedi anche Test per l'iniezione SQL su owasp.org per alcuni dettagli.

    
risposta data 23.12.2014 - 14:11
fonte
4

O non ci sono quasi vincoli e puoi farlo nel solito modo (UNION o '; XXX ---')

A volte non è possibile, e dovrai fare una ricaduta sul mettere un'espressione booleana nel LIMIT. Questa è un'iniezione SQL cieca, e ti permetterà di scaricare l'intero database un bit alla volta.

    
risposta data 23.12.2014 - 15:35
fonte
3

MySQL supporta più istruzioni e da allora ha almeno 4,1 dieci anni fa. Ad esempio, puoi attivarlo nel mysl di Perl modulo che utilizza mysql_multi_statements .

Sebbene al momento la libreria client non supporti più istruzioni multiple, sei solo un aggiornamento o una modifica della configurazione da una falla nella sicurezza.

    
risposta data 24.12.2014 - 05:27
fonte
1

L'impostazione di un limite di 1 UNION SELECT ... consente all'utente malintenzionato di estrarre informazioni da qualsiasi altra tabella, a condizione che le colonne abbiano (o possano essere CAST ) lo stesso numero e tipo delle colonne nel primo %codice%. L'impostazione di un limite come valore prodotto da una percentuale parziale di% equivale a consentire all'utente malintenzionato di leggere qualsiasi altra informazione nel database dal numero di righe restituite. Ad esempio, l'hash della password di un altro utente può essere estratto a 4 bit alla volta eseguendo ripetutamente una sottosquadri restituendo un numero compreso tra 0 e 15 a diversi offset di sottostringa e quindi contando le righe in ogni risultato.

Ma entrambi questi attacchi possono essere vanificati. Molti driver di database consentono un parametrizzato SELECT . Se un determinato driver interferisce con una percentuale parametrizzata diSELECT, è possibile disinfettare l'input convertendo l'input in un intero prima di sostituirlo con la stringa nella query. Ciò ti aiuterà anche a non restituire più record di quelli che l'applicazione può gestire da una query (come LIMIT ). In PHP, potrebbe assomigliare a questo:

<?php
//...
$limit = intval($_REQUEST['numresults']);
$limit = min(max($limit, 10), 100);
$stmt = $dbh->prepare("SELECT ... FROM ... WHERE ... LIMIT $limit");
    
risposta data 23.12.2014 - 20:30
fonte
1

Questo è un buon momento per usare le istruzioni preparate PDO e bindParam quella variabile come input solo per interi. Questo dovrebbe annullare qualsiasi tentativo di ciò che stai cercando di fare iniettando SQL.

Prenderò in considerazione la possibilità di consentire all'utente di scegliere da un elenco predefinito di numeri in un menu a discesa. A meno che la pagina dei risultati non sia impostata per impaginare, puoi potenzialmente avere un bel casino in mano cercando di caricare 100.000 record in una pagina.

    
risposta data 25.12.2014 - 04:42
fonte
1

La query del tuo amico non sarebbe di grande utilità oggi, ma potrebbe essere in seguito, ma con l'evolversi delle tecnologie, e MySQL DBMS è sotto costante miglioramento come molte altre tecnologie, il tuo amico deve disinfettare l'input nel caso della% la dichiarazione diLIMIT verrebbe modificata in modo che fosse possibile utilizzare UNION subito dopo. Il tuo amico potrebbe anche considerare il caso in cui l'architettura di MySQL DBMS sarebbe stata modificata in modo tale che sarebbe stato possibile eseguire più istruzioni SQL diversamente da come è ora.

Quello che voglio dire è che il tuo amico deve disinfettare l'input: è la migliore pratica: potresti non vederlo troppo importante oggi, ma in futuro non lo saprai mai, e ricorda che ci sono sempre persone che potrebbero essere più esperto del tuo amico.

    
risposta data 23.12.2014 - 12:41
fonte

Leggi altre domande sui tag