web-dev-qa-db-fra.com

Python meilleures pratiques et plus sécurisées pour se connecter à MySQL et exécuter des requêtes

Quelle est la façon la plus sûre d'exécuter des requêtes sur mysql, je suis conscient des dangers liés à l'injection MySQL et SQL.

Cependant, je ne sais pas comment exécuter mes requêtes pour empêcher l'injection sur les variables que d'autres utilisateurs (webclients) peuvent manipuler. J'avais l'habitude d'écrire ma propre fonction d'échappement, mais apparemment, ce n'est "pas fait".

Que dois-je utiliser et comment dois-je l'utiliser pour interroger et faire des insertions en toute sécurité sur une base de données MySQL via python sans risquer l'injection mysql?

54
Lucas Kauffman

Pour éviter les injections, utilisez execute avec %s à la place de chaque variable, puis passez la valeur via une liste ou un Tuple comme deuxième paramètre de execute. Voici un exemple de la documentation :

c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""", (max_price,))

Notez que cela utilise une virgule , pas % (qui serait une substitution de chaîne directe, non échappée). Ne faites pas cela :

c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""" % (max_price,))

De plus, vous n'avez pas besoin des guillemets autour du support de position ('%s') si le paramètre est une chaîne.

78
Bruno

En tant qu'extension de la réponse de Bruno, votre bibliothèque client MySQL peut prendre en charge plusieurs formats différents pour spécifier des paramètres nommés. Depuis PEP 249 (DB-API) , vous pouvez écrire vos requêtes comme:

"qmark"

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = ?", (lumberjack,))

"numérique"

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = :1", (lumberjack,))

'nommé'

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = :jack", {'jack': lumberjack})

'format'

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = %s", (lumberjack,))

"pyformat"

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = %(jack)s", {'jack': lumberjack})

Vous pouvez voir ce que votre bibliothèque cliente prend en charge en consultant la variable au niveau du module paramstyle:

>>> clientlibrary.paramstyle
'pyformat'

L'une des options ci-dessus devrait faire ce qu'il faut en ce qui concerne le traitement de vos données potentiellement non sécurisées. Comme l'a souligné Bruno, n'essayez jamais d'insérer des paramètres vous-même. Les bibliothèques clientes couramment utilisées sont bien meilleures pour traiter correctement les données que nous, simples mortels, ne le serons jamais.

71
Kirk Strauser