2009-03-26 9 views
13

Qualcuno potrebbe indicarmi una buona guida per principianti sull'esecuzione in sicurezza di query SQL formate in parte dall'input dell'utente? Sto usando Java, ma una guida neutra per la lingua va bene.Come devo disinfettare l'input del database in Java?

il comportamento desiderato è che se qualcuno nel qualcosa di simile GUI

very nice;) DROP TABLE FOO;

La banca dati dovrebbe trattarlo come una stringa letterale e conservarlo in modo sicuro senza far cadere tutte le tabelle.

risposta

5

Normalmente, non si deve creare una query concatenazione di ingresso, ma utilizzando invece PreparedStatement.

Ciò consente di specificare in quali posti si impostano i parametri all'interno della query, quindi Java si prenderà cura di disinfettare tutti gli input per voi.

3

PreparedStatement? Si assolutamente. Ma penso che ci sia un altro passo: la convalida dell'input dall'interfaccia utente e il binding agli oggetti prima di avvicinarsi al database.

posso vedere dove l'associazione di una stringa in PreparedStatement potrebbe ancora lasciare vulnerabile ad un attacco SQL injection:

String userInput = "Bob; DELETE FROM FOO"; 
String query = "SELECT * FROM FOO WHERE NAME = ?"; 

PreparedStatement ps = connection.prepareStatement(query); 
ps.setString(1, userInput); 
ps.executeQuery(); 

ho devo ammettere che non ho provato io stesso, ma se questo è in modalità remota possibile direi che PreparedStatement è necessario ma non sufficiente. La convalida e il binding sul lato server è la chiave.

Suggerirei di farlo con l'API di binding di Spring.

+0

Questo è esattamente il tipo di attacco che le dichiarazioni preparate sono destinate a proteggere contro. Sfuggirà il; – danieltalsky

+0

Tecnicamente l'interfaccia PreparedStatement non lo garantisce. Anche se il tuo autista fa qualcosa di diverso, trova un nuovo fornitore. –

+0

@daniel - Dovrò provarlo e vedere di persona. Che io sia corretto o meno, non sei d'accordo che la validazione lato server sia ancora una buona idea? – duffymo

3

Il vostro input dell'utente sarebbe in realtà dovuto essere "Bob'; delete from foo; select '" (o qualcosa di simile) in modo che le citazioni implicite aggiunti dal dichiarazione preparata sarebbe stato chiuso:

SELECT * FROM FOO WHERE NAME = 'Bob'; delete from foo; select '' 

ma se lo fate che il codice dichiarazione preparata citerà il tuo preventivo in modo da ottenere una query effettiva di

SELECT * FROM FOO WHERE NAME = 'Bob''; delete from foo; select ''' 

e il tuo nome sarebbe stato archiviato come "Bob', delete from foo; select '" invece di eseguire più query.

Problemi correlati