SQL injection può bypassare l'accesso ma non eliminare la tabella

14

Ho installato un ambiente di test per eseguire alcuni SQL Injection contro il mio codice e per imparare a difenderci. Posso ignorare il modulo di accesso utilizzando quanto segue nel campo password:

' OR username = 'admin

Quale mi dà la query:

SELECT * FROM customer_data WHERE username = '' AND password = '' OR username = 'admin'

Funziona bene ma ho problemi con il rilascio di un tavolo. Ho provato vari tentativi sulla falsariga di inserire qualcosa di simile nel campo della password:

OR '1' = '1'; DROP TABLE temp; --

Ho creato una tabella chiamata temp solo per provarla, ma non ho potuto pensare a nulla che abbia funzionato. Se accedo al PHP MyAdmin (stesse credenziali utilizzate dalla pagina) posso inserire manualmente la query che sarebbe stata costruita sopra e funziona perfettamente.

    
posta Scott Helme 22.07.2013 - 09:21
fonte

3 risposte

34

Risposta alla tua domanda

mysql_query() non supporta più query come documentato:

mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.

Ciò significa che DROP TABLE temp; -- non viene mai eseguito.
È comunque possibile se usi mysqli::multi_query o usando PDO .

Best practice

Avviso? Vedi questa casella rossa di avviso ? L'estensione mysql è in fase di deprecazione e genererà avvisi a partire da PHP 5.5.0. Ci sono anche piani per abbandonarlo completamente in PHP 5.6 o PHP 6.0 fonte . Tieni presente che mysql_ non è infranto come dichiarato da Ángel González:

The extension is not broken. The problem is the bad usage. It can be used safely, and good developers have been doing so for ages, by creating php wrappers. In magic quotes, the work has been the opposite. The developers had been detecting the feature in php and disabling it.

Il nuovo standard
Il nuovo standard è MySQLi o PDO . Non confronterò le due estensioni qui, ma ci sono davvero un sacco di buone caratteristiche, specialmente da PHP 5.3+, che ti faranno risparmiare tempo e sforzi. Nota che l'uso di MySQLi / PDO non ti proteggerà da solo dalle iniezioni SQL. L'opzione migliore sarebbe utilizzare istruzioni preparate . I dati vengono inviati separatamente dalla query, rendendo impossibile l'immissione di valori. Questo è ben spiegato da Anthony Ferrara in questo video .

Fai attenzione
Ma aspetta "impossibile"? Sembra troppo bello :)
Per esempio, abbiamo due gruppi: group1 & group2. C'è un certo file php deleteUser.php che ottiene un id da $_GET .
L'istruzione preparata assomiglia a questo: DELETE FROM users WHERE id = ? . Quando la query viene eseguita con $_GET['id'] , l'utente con ID = $_GET['id'] verrà eliminato. Ehi, ma questo significa che gli utenti di group1 potrebbero cancellare utenti da group2 usando quell'ID che non è inteso. Quindi possiamo modificare la query in qualcosa come DELETE FROM users WHERE id = ? AND group = ? e inviare il nome del gruppo dell'utente in cui si trova insieme alla query.
Breve: le dichiarazioni preparate non ti proteggeranno da difetti logici.

Query multipla? Non hai bisogno di più richieste. Se vuoi fare due cose, fallo separatamente, ti darà più controllo sulle tue query e renderà il tuo codice più leggibile.

Su un'altra nota: Se stai facendo dinamicamente e buttando i tavoli, molto probabilmente stai sbagliando. Dovresti progettare il tuo database in modo tale che non sia necessario. Ovviamente ci possono essere delle eccezioni, ma sono per lo più eliminati perché potresti cercare una soluzione NoSQL (altro motore db).

TL; DR

  • Smetti di utilizzare le funzioni mysql_ e passa a MySQLi o DOP
  • Utilizza le istruzioni preparate, tieni presente che non ti proteggerà dagli attacchi se non proteggi la logica dietro di esso
  • Non utilizzare più query
  • Crea un buon progetto di DB
  • Se vuoi allenare le tue capacità di hacking, puoi controllare OS vulnerabili?
risposta data 22.07.2013 - 13:27
fonte
10

Potrebbe essere che la funzione che usi in PHP non ammette query impilate o perché l'utente che è configurato per eseguire le interrogazioni non ha privilegi di drop table. Ti suggerisco di registrare tutti gli output e le eccezioni lanciate dall'applicazione. Potrebbe dare un indizio su dove si trova il tuo problema.

MODIFICA 1: anziché eseguire la query, stampala sullo schermo.

    
risposta data 22.07.2013 - 09:26
fonte
4

Questa è stata una svista da parte mia dopo una lettura a tarda notte della documentazione!

mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.

    
risposta data 22.07.2013 - 10:02
fonte

Leggi altre domande sui tag