Le procedure memorizzate non impediscono magicamente l'iniezione di SQL, ma rendono molto più semplice prevenirlo. Tutto quello che devi fare è qualcosa di simile al seguente (esempio Postgres):
CREATE OR REPLACE FUNCTION my_func (
IN in_user_id INT
)
[snip]
SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
[snip]
Questo è tutto! Il problema si presenta solo quando si forma una query tramite concatenazione di stringhe (ovvero SQL dinamico) e anche in quei casi potresti essere in grado di legare! (Dipende dal database.)
Come evitare l'iniezione SQL nella query dinamica:
Passaggio 1) Chiediti se hai davvero bisogno di una query dinamica. Se stai mettendo insieme le stringhe solo per impostare l'input, probabilmente stai sbagliando. (Esistono eccezioni a questa regola: un'eccezione è per la segnalazione di query su alcuni database, potresti avere problemi di prestazioni se non lo costringi a compilare una nuova query con ogni esecuzione. Ma cerca questo problema prima di saltare a quello. )
Passaggio 2) Ricercare il modo corretto di impostare la variabile per il proprio RDBMS. Ad esempio, Oracle ti consente di fare quanto segue (citando dai loro documenti):
sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE '
|| v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!
Qui non stai ancora concatenando l'input. Stai vincolando in modo sicuro! Evviva!
Se il tuo database non supporta qualcosa di simile a quanto sopra (speriamo che nessuno di loro sia ancora così male, ma non sarei sorpreso) - o se devi ancora concatenare il tuo input (come nel caso "a volte" di segnalazione di query come Ho accennato sopra), quindi è necessario utilizzare una corretta funzione di escape. Non scriverlo da solo. Ad esempio postgres fornisce la funzione quote_literal (). Quindi avresti eseguito:
sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);
In questo modo se in_name è qualcosa di subdolo come '[snip] o 1 = 1' (la parte "o 1 = 1" significa selezionare tutte le righe, permettendo all'utente di vedere gli stipendi che non dovrebbe!), Allora quote_literal salva il tuo sedere di rendendo la stringa risultante:
SELECT salary FROM employees WHERE name = '[snip] or 1=1'
Nessun risultato verrà trovato (a meno che tu non abbia alcuni dipendenti con nomi davvero strani.)
Questa è la sostanza! Ora lascia che ti lasci un link a un post classico del guru Oracle Tom Kyte sull'argomento SQL Injection, per riportare il punto a casa: Linky