web-dev-qa-db-fra.com

SQLAlchemy + injection SQL

Quelles sont les meilleures pratiques pour atténuer les attaques par injection SQL lors de l'utilisation de SQLAlchemy?

50
Mike

Si vous avez des caractères "spéciaux" (tels que des points-virgules ou des apostrophes) dans vos données, ils seront automatiquement cités pour vous par l'objet SQLEngine, vous n'avez donc pas à vous soucier de les citer. Cela signifie également qu'à moins de contourner délibérément les mécanismes de cotation de SQLAlchemy, les attaques par injection SQL sont fondamentalement impossibles.

[par http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html ]

45
Andreas Jung

tldr: évitez autant que possible le SQL brut.

La réponse acceptée est paresseuse et incorrecte. La méthode de filtrage accepte le SQL brut et, si elle est utilisée de cette manière, est entièrement sensible aux attaques par injection SQL. Par exemple, si vous deviez accepter une valeur d'une URL et la combiner avec SQL brut dans le filtre, vous êtes ouvert à attaquer:

session.query(MyClass).filter("foo={}".format(getArgs['val']))

en utilisant le code ci-dessus et l'url ci-dessous, vous injecteriez du SQL dans votre instruction de filtrage. Le code ci-dessus retournerait toutes les lignes de votre base de données.

http://domain.com/?val=2%20or%201%20=%201

63
Tendrid

Pour ajouter à @ réponse Tendrid . J'ai fait une petite enquête en utilisant une approche naïve silencieuse. filter la méthode a *criterion comme argument, plusieurs autres méthodes de requête ORM ont un argument similaire.

En cas de filter méthode *criterion l'argument finit par être passé dans _ literal_as_text , qui en cas de chaîne - le marque comme sql sûr (veuillez me corriger si je me trompe). Par conséquent, cela le rend dangereux.

Voici le résultat de classe ORM Query investigation de méthode avec *criterion argument:

filter   - uses _literal_as_text (NOT SAFE)
having   - uses _literal_as_text (NOT SAFE)

distinct - uses _literal_as_label_reference (NOT SAFE)
group_by - uses _literal_as_label_reference (NOT SAFE)
order_by - uses _literal_as_label_reference (NOT SAFE)

join     - uses model attributes to resolve relation (SAFE)

Exemples de possibles erreurs de méthode (pour rester simple, le formatage des chaînes est ignoré):

db.session.query(User.login).group_by('login').having('count(id) > 4; select name from roles').all()
db.session.query(User.login).distinct('name) name from roles /*').order_by('*/').all()
db.session.query(User.login).order_by('users_login; select name from roles').all()
db.session.query(User.login).group_by('login union select name from roles').all()

Notez que ces méthodes ne sont dangereuses que si le littéral de chaîne est passé.

5
aisbaa