2009-03-26 6 views
13

Quelqu'un pourrait-il me diriger vers un bon guide de débutant sur l'exécution en toute sécurité des requêtes SQL formées en partie à partir de l'entrée de l'utilisateur? J'utilise Java, mais un guide de langue neutre est bien aussi.Comment désinfecter l'entrée de la base de données en Java?

Le comportement souhaité est que si quelqu'un tape dans quelque chose comme interface graphique

very nice;) DROP TABLE FOO;

La base de données devrait le traiter comme une chaîne littérale et le stocker en toute sécurité sans laisser tomber toutes les tables.

Répondre

5

Normalement, vous ne devriez pas créer une entrée concaténer requête, mais en utilisant PreparedStatement à la place. Cela vous permet de spécifier dans quels endroits vous allez définir vos paramètres dans votre requête, afin que Java s'occupe de désinfecter toutes les entrées pour vous.

3

PreparedStatement? Oui absolument. Mais je pense qu'il y a une étape de plus: la validation de l'entrée de l'interface utilisateur et la liaison aux objets avant de se rapprocher de la base de données.

Je peux voir où lier une chaîne en PreparedStatement peut encore vous rendre vulnérable à une attaque par injection SQL:

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

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

J'ai dois admettre que je ne l'ai pas essayé moi-même, mais si cela est à distance Possible Je dirais PreparedStatement est nécessaire mais pas suffisant. La validation et la liaison côté serveur est la clé.

Je recommande de le faire avec l'API de liaison de Spring.

+0

C'est exactement le type d'attaque contre lequel les instructions préparées sont censées se protéger. Il va échapper à. – danieltalsky

+0

Techniquement, l'interface PreparedStatement ne le garantit pas. Bien que votre chauffeur fasse quelque chose de différent, trouvez un nouveau fournisseur. –

+0

@daniel - Je vais devoir l'essayer et voir par moi-même. Que ce soit correct ou non, n'êtes-vous pas d'accord pour dire que la validation côté serveur est toujours une bonne idée? – duffymo

3

Votre entrée utilisateur aurait en fait être "Bob'; delete from foo; select '" (ou quelque chose comme ça) si les citations implicites ajoutées par la déclaration préparée seraient fermées:

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

mais si vous le faites que le code de déclaration préparée citerons votre devis afin que vous obteniez une requête réelle de

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

et votre nom sera stocké sous forme "Bob', delete from foo; select '" au lieu d'exécuter plusieurs requêtes.

Questions connexes