Un'iniezione SQL può distruggere la vostra base di dati.
SQL nelle pagine Web
Nei capitoli precedenti, avete imparato a recuperare i dati del database (e aggiornare), utilizzando SQL.
Quando SQL viene utilizzato per visualizzare i dati in una pagina web, è comune per permettere di ingresso gli utenti di Internet i propri valori di ricerca.
Dal momento che le istruzioni SQL sono solo testo, è facile, con un piccolo pezzo di codice di computer, per modificare dinamicamente le istruzioni SQL per fornire all'utente i dati selezionati:
codice del server
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
L'esempio di cui sopra, crea un'istruzione select con l'aggiunta di una variabile (txtUserId) in una stringa di selezione. La variabile prelevato dalla input dell'utente (Request) alla pagina.
Il resto di questo capitolo descrive i potenziali pericoli di utilizzare l'input dell'utente in istruzioni SQL.
SQL Injection
SQL injection è una tecnica in cui utenti malintenzionati possono iniettare comandi SQL in un'istruzione SQL, tramite l'ingresso pagina web.
comandi SQL iniettati possono alterare istruzione SQL e compromettere la sicurezza di un'applicazione web.
SQL Injection Sulla base 1 = 1 è sempre vero
Guardate l'esempio di cui sopra, ancora una volta.
Diciamo che lo scopo originale del codice era quello di creare un'istruzione SQL per selezionare un utente con un dato id utente.
Se non vi è nulla per impedire a un utente di entrare "wrong" di ingresso, l'utente può inserire un po 'di "smart" di ingresso in questo modo:
ID utente:
Risultato Server
SELECT * FROM Users WHERE UserId = 105 or 1=1
L'SQL di cui sopra è valido. Si restituirà tutte le righe della tabella degli utenti, dal momento che dove 1 = 1 è sempre vero.
Fa l'esempio di cui sopra sembrano pericoloso? Che cosa se la tabella Utenti contiene i nomi e le password?
L'istruzione SQL di cui sopra è molto simile a quello presente:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1
Un hacker intelligente potrebbe ottenere l'accesso a tutti i nomi utente e le password in un database, semplicemente inserendo 105 o 1 = 1 nella casella di input.
SQL Injection Sulla base di ""="" è sempre vero
Qui è una costruzione comune, utilizzato per verificare il login utente a un sito web:
Nome utente:
Parola d'ordine:
codice del server
uName = getRequestString("UserName");
uPass = getRequestString("UserPass");
sql = "SELECT * FROM Users WHERE Name ='" + uName + "' AND Pass ='" + uPass + "'"
Un hacker intelligente potrebbe ottenere l'accesso a nomi utente e password in un database, semplicemente inserendo "o ""=" nel nome utente o la password casella di testo.
Il codice sul server creerà un'istruzione SQL valida in questo modo:
Risultato
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
Il SQL risultato è valido. Si restituirà tutte le righe della tabella degli utenti, dal momento che dove "" = "" è sempre vero.
SQL Injection Sulla base di istruzioni SQL batch
La maggior parte dei database supportano istruzione SQL in batch, separati da virgola.
Esempio
SELECT * FROM Users; DROP TABLE Suppliers
Il SQL sopra restituirà tutte le righe della tabella Utenti, e quindi eliminare la tabella denominata Fornitori.
Se avessimo il seguente codice del server:
codice del server
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
E il seguente comando:
ID utente:
Il codice sul server creerebbe un'istruzione SQL valida in questo modo:
Risultato
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers
I parametri per la protezione
Alcuni sviluppatori web utilizzano una "blacklist" di parole o caratteri da cercare nel ingresso SQL, per prevenire attacchi di SQL injection.
Questa non è una buona idea. Molte di queste parole (come cancellare o cadere) e personaggi (come il punto e virgola e virgolette), sono utilizzati nel linguaggio comune, e dovrebbe essere permesso in molti tipi di input.
(In realtà dovrebbe essere perfettamente legale per inserire un'istruzione SQL in un campo di database.)
L'unico modo dimostrato di proteggere un sito web da attacchi di SQL injection, è quello di utilizzare parametri SQL.
parametri SQL sono valori che vengono aggiunti a una query SQL in fase di esecuzione, in modo controllato.
ASP.NET Razor Esempio
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Si noti che i parametri sono rappresentate nell'istruzione SQL da un indicatore @.
Il motore SQL controlla ogni parametro per assicurarsi che sia corretta per la colonna e sono trattati letteralmente, e non come da eseguire parte del SQL.
Un altro esempio
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City)
Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);
Hai appena imparato ad evitare SQL injection. Uno dei principali vulnerabilità dei siti Web.
Esempi
Gli esempi che seguono mostrano come costruire query con parametri in alcuni linguaggi web più comuni.
SELECT in ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserID);
command.ExecuteReader();
INSERT INTO in ASP.NET:
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City)
Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();
INSERT INTO in PHP:
$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();