Le altre risposte coprono già ciò che devi sapere. Ma forse aiuta a chiarire un po 'di più:
Ci sono DUE COSE che devi fare:
1. Convalida i dati del modulo.
Come la risposta di Jonathan Hobbs mostra molto chiaramente, la scelta dell'elemento html per l'input del modulo non fa alcun filtro affidabile per te.
La convalida viene solitamente eseguita in un modo che non altera i dati, ma che mostra di nuovo il modulo, con i campi contrassegnati come "Correggi questo".
La maggior parte dei framework e dei CMS dispone di form builder che ti aiutano in questa attività. E non solo, aiutano anche contro CSRF (o "XSRF"), che è un'altra forma di attacco.
2. Disinfetta / Esci dalle variabili nelle istruzioni SQL ..
.. o lascia che le dichiarazioni preparate facciano il lavoro per te.
Se si crea un'istruzione (My) SQL con qualsiasi variabile, fornita dall'utente o meno, è necessario eseguire l'escape e citare queste variabili.
In genere, qualsiasi variabile di questo tipo inserita in un'istruzione MySQL dovrebbe essere una stringa o qualcosa che PHP può essere trasformato in modo affidabile in una stringa che MySQL può digerire. Come i numeri.
Per le stringhe, è quindi necessario scegliere uno dei diversi metodi per eseguire l'escape della stringa, ovvero sostituire tutti i caratteri che avrebbero effetti collaterali in MySQL.
- Nella vecchia scuola MySQL + PHP, mysql_real_escape_string () fa il lavoro. Il problema è che è troppo facile da dimenticare, quindi dovresti assolutamente usare istruzioni preparate o costruttori di query.
- In MySQLi, puoi utilizzare istruzioni preparate.
- La maggior parte dei framework e dei CMS fornisce generatori di query che ti aiutano in questa attività.
Se hai a che fare con un numero, puoi omettere l'escape e le virgolette (questo è il motivo per cui le istruzioni preparate consentono di specificare un tipo).
È importante sottolineare che esegui l'escape delle variabili per l'istruzione SQL e NON per il database stesso . Il database memorizzerà la stringa originale, ma l'istruzione necessita di una versione con escape.
Cosa succede se ometti uno di questi?
Se non utilizzi la convalida del modulo , ma disinfetti l'input SQL, potresti vedere accadere tutti i tipi di cose brutte, ma non vedrai SQL injection! (*)
In primo luogo, può portare la tua domanda in uno stato che non avevi pianificato. Ad esempio, se si desidera calcolare l'età media di tutti gli utenti, ma un utente ha fornito "aljkdfaqer" per l'età, il calcolo fallirà.
In secondo luogo, possono esserci tutti i tipi di altri attacchi injection che devi considerare: ad esempio, l'input dell'utente potrebbe contenere javascript o altro.
Possono ancora esserci problemi con il database: ad esempio, se un campo (colonna della tabella del database) è limitato a 255 caratteri e la stringa è più lunga di quella. Oppure se il campo accetta solo numeri e si tenta invece di salvare una stringa non numerica. Ma questa non è "iniezione", è solo "arresto anomalo dell'applicazione".
Ma, anche se si dispone di un campo di testo libero in cui si consente qualsiasi input senza alcuna convalida, è comunque possibile salvarlo nel database proprio in questo modo, se si evita correttamente quando si passa a un'istruzione del database. Il problema nasce quando vuoi usare questa stringa da qualche parte.
(*) o questo sarebbe qualcosa di veramente esotico.
Se non esegui l'escape delle variabili per le istruzioni SQL , ma hai convalidato l'input del modulo, puoi comunque vedere accadere cose brutte.
Innanzitutto, rischi che quando salvi i dati nel database e li carichi di nuovo, non saranno più gli stessi dati, "persi nella traduzione".
In secondo luogo, può causare istruzioni SQL non valide e quindi bloccare l'applicazione. Ad esempio, se una variabile contiene virgolette o virgolette doppie, a seconda del tipo di virgolette utilizzate, si otterrà un'istruzione MySQL non valida.
In terzo luogo, può ancora causare SQL injection.
Se l'input dell'utente dai moduli è già filtrato / convalidato, l' iniezione SQl intenzionale potrebbe diventare meno probabile, SE l'input è ridotto a un elenco di opzioni codificato o è limitato a numeri. Ma qualsiasi input di testo libero può essere utilizzato per l'iniezione SQL, se non si esegue correttamente l'escape delle variabili nelle istruzioni SQL.
E anche se non hai alcun input dal modulo, potresti comunque avere stringhe da tutti i tipi di fonti: lette dal filesystem, raschiate da Internet, ecc. Nessuno può garantire che queste stringhe siano sicure.
<select>
input. Infatti anche un utente leggermente tecnico potrebbe aggiungere ulteriori opzioni utilizzando la console del browser. se mantieni una whitelist di array di valori disponibili e confronti l'input con esso, puoi mitigarlo (e dovresti perché impedisce valori indesiderati)