Per quanto riguarda molte risposte utili, spero di aggiungere un po 'di valore a questa discussione.
L'iniezione SQL è un attacco che può essere eseguito tramite input dell'utente (input compilati da un utente e quindi utilizzati all'interno delle query). I modelli di iniezione SQL sono sintassi della query corretta mentre possiamo chiamarla: query errate per motivi errati e supponiamo che potrebbe esserci una persona cattiva che tenta di ottenere informazioni segrete (ignorando il controllo degli accessi) che influiscono sui tre principi di sicurezza (riservatezza , integrità e disponibilità).
Ora, il nostro punto è prevenire minacce alla sicurezza come gli attacchi di SQL injection, la domanda (come prevenire un attacco di SQL injection usando PHP), essere più realistici, il filtraggio dei dati o la cancellazione dei dati di input è il caso quando si utilizzano i dati di input dell'utente all'interno tale query, utilizzando PHP o qualsiasi altro linguaggio di programmazione non è il caso, o come raccomandato da più persone di utilizzare la tecnologia moderna come dichiarazioni preparate o altri strumenti che attualmente supportano la prevenzione dell'iniezione SQL, ritengono che questi strumenti non siano più disponibili? Come si protegge l'applicazione?
Il mio approccio contro l'iniezione SQL è: cancellare i dati immessi dall'utente prima di inviarli al database (prima di usarli all'interno di qualsiasi query).
Filtro dati per (conversione di dati non sicuri in dati sicuri)
Considera che DOP e MySQLi non sono disponibili. Come puoi proteggere la tua applicazione? Mi costringi ad usarli? Che dire di altre lingue diverse da PHP? Preferisco fornire idee generali in quanto possono essere utilizzate per confini più ampi, non solo per una lingua specifica.
- Utente SQL (limitazione del privilegio utente): le operazioni SQL più comuni sono (SELEZIONA, AGGIORNA, INSERISCI), quindi perché assegnare il privilegio AGGIORNAMENTO a un utente che non lo richiede? Ad esempio, le pagine di accesso e di ricerca utilizzano solo SELECT, quindi perché utilizzare gli utenti DB in queste pagine con privilegi elevati?
REGOLA: non creare un utente del database per tutti i privilegi. Per tutte le operazioni SQL, puoi creare il tuo schema come (deluser, selectuser, updateuser) come nomi utente per un facile utilizzo.
Vedi il principio del privilegio minimo .
Filtro dati: prima di creare qualsiasi input dell'utente per la query, deve essere convalidato e filtrato. Per i programmatori, è importante definire alcune proprietà per ciascuna variabile di input dell'utente:
tipo di dati, modello di dati e lunghezza dei dati . Un campo che è un numero compreso tra (xey) deve essere validato esattamente usando la regola esatta, e per un campo che è una stringa (testo): modello è il caso, ad esempio, un nome utente deve contenere solo alcuni caratteri, dire [a-zA-Z0-9_-.]. La lunghezza varia tra (x e n) dove x e n (numeri interi, x <= n).
Regola: la creazione di filtri esatti e regole di convalida sono le migliori pratiche per me.
Utilizza altri strumenti: qui, concorderò anche con te che una dichiarazione preparata (query parametrizzata) e procedure memorizzate. Gli svantaggi qui sono che questi modi richiedono competenze avanzate che non esistono per la maggior parte degli utenti. L'idea di base qui è di distinguere tra la query SQL e i dati utilizzati all'interno. Entrambi gli approcci possono essere utilizzati anche con dati non sicuri, poiché i dati immessi dall'utente qui non aggiungono nulla alla query originale, come (any o x = x).
Per ulteriori informazioni, consultare il foglio informativo OWASP SQL Injection Prevention Prevention .
Ora, se sei un utente avanzato, inizia a utilizzare questa difesa a tuo piacimento, ma, per i principianti, se non sono in grado di implementare rapidamente una procedura memorizzata e hanno preparato la dichiarazione, è meglio filtrare i dati di input il più possibile.
Infine, consideriamo che un utente invia questo testo qui sotto invece di inserire il suo nome utente:
[1] UNION SELECT IF(SUBSTRING(Password,1,1)='2',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = 'root'
Questo input può essere verificato in anticipo senza alcuna istruzione preparata e stored procedure, ma per essere al sicuro, il loro utilizzo inizia dopo il filtraggio e la convalida dei dati utente.
L'ultimo punto è rilevare comportamenti inaspettati che richiedono maggiore sforzo e complessità; non è raccomandato per le normali applicazioni Web.
Il comportamento imprevisto nell'input dell'utente sopra è SELECT, UNION, IF, SUBSTRING, BENCHMARK, SHA e root. Una volta rilevate queste parole, è possibile evitare l'input.
AGGIORNAMENTO 1:
Un utente ha commentato che questo post è inutile, OK! Ecco cosa ha fornito OWASP.ORG :
Difese primarie:
Opzione n. 1: utilizzo di istruzioni preparate (query con parametri)
Opzione n. 2: utilizzo di procedure memorizzate
Opzione n. 3: fuga da tutti gli input forniti dall'utente
Difese aggiuntive:
Applicazione anche: privilegio minimo
Esecuzione: convalida input lista bianca
Come forse saprai, rivendicare un articolo dovrebbe essere supportato da un argomento valido, almeno da un riferimento! Altrimenti, è considerato un attacco e una cattiva pretesa!
Aggiornamento 2:
Dal manuale di PHP, PHP: Istruzioni preparate - Manuale :
Escaping e SQL injection
Le variabili associate verranno salvate automaticamente dal server. Il server inserisce i valori di escape nei punti appropriati nel modello di istruzione prima dell'esecuzione. È necessario fornire un suggerimento al server per il tipo di variabile associata, per creare una conversione appropriata. Vedere la funzione mysqli_stmt_bind_param () per ulteriori informazioni.
L'escaping automatico dei valori all'interno del server è talvolta considerato una funzionalità di sicurezza per impedire l'iniezione di SQL. Lo stesso grado di sicurezza può essere raggiunto con istruzioni non preparate se i valori di input vengono salvati correttamente.
Aggiornamento 3:
Ho creato casi di test per sapere come PDO e MySQLi inviano la query al server MySQL quando si utilizza un'istruzione preparata:
DOP:
$user = "''1''"; // Malicious keyword
$sql = 'SELECT * FROM awa_user WHERE userame =:username';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $user));
Registro query:
189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\''
189 Quit
MySQLi:
$stmt = $mysqli->prepare("SELECT * FROM awa_user WHERE username =?")) {
$stmt->bind_param("s", $user);
$user = "''1''";
$stmt->execute();
Registro query:
188 Prepare SELECT * FROM awa_user WHERE username =?
188 Execute SELECT * FROM awa_user WHERE username ='\'\'1\'\''
188 Quit
È chiaro che anche un'istruzione preparata sta sfuggendo ai dati, nient'altro.
Come menzionato anche nella precedente dichiarazione,
L'escaping automatico dei valori all'interno del server è talvolta considerato una funzionalità di sicurezza per impedire l'iniezione di SQL. Lo stesso grado di sicurezza può essere raggiunto con istruzioni non preparate, se i valori di input vengono evitati correttamente
Pertanto, ciò dimostra che la convalida dei dati come intval()
una buona idea per i valori interi prima di inviare qualsiasi query. Inoltre, la prevenzione di dati utente dannosi prima di inviare la query è un approccio corretto e valido .
Vedi questa domanda per maggiori dettagli: PDO invia query non elaborate a MySQL mentre Mysqli invia query preparate, entrambe producono lo stesso risultato
Riferimenti:
- Foglio informativo sull'iniezione SQL
- SQL Injection
- Informazioni di sicurezza
- Principi di sicurezza
- Convalida dei dati