Maison >développement back-end >Tutoriel Python >Explication détaillée des méthodes Python pour empêcher l'injection SQL

Explication détaillée des méthodes Python pour empêcher l'injection SQL

Y2J
Y2Joriginal
2017-05-06 15:02:511378parcourir

L'injection SQL est l'une des méthodes d'attaque réseau les plus courantes. Elle n'utilise pas le BUG du système d'exploitation pour réaliser l'attaque, mais cible la négligence du programmeur lors de la programmation, elle peut se connecter sans compte ou. même falsifier la base de données. L'article suivant vous présente principalement les méthodes pour empêcher l'injection SQL dans Python. Les amis dans le besoin peuvent s'y référer.

Avant-propos

Tout le monde devrait savoir que la vulnérabilité Web numéro un est désormais SQL, quel que soit le langage utilisé pour le développement back-end Web. , Tant que vous utilisez une base de données relationnelle, vous pouvez rencontrer des attaques par injection SQL. Alors, comment l'injection SQL apparaît-elle lors du développement Web Python et comment résoudre ce problème ?

Bien sûr, je ne veux pas discuter de la façon dont d'autres langages évitent l'injection SQL. Il existe différentes manières d'empêcher l'injection en PHP (note du blogueur : on dit que c'est le langage le plus génial au monde). ) sur Internet, y compris Python. Les méthodes sont en fait similaires, je vais donc vous donner un exemple ici.

Cause

La cause la plus courante de la vulnérabilité est l'épissage de chaîne Bien sûr, l'injection SQL n'existe pas. n'est qu'un cas d'épissage, mais il existe de nombreux autres types tels que l'injection d'octets larges, les caractères spéciaux s'échappant, etc. Nous parlerons ici de l'épissage de chaînes le plus courant, qui est également l'erreur la plus courante pour programmeurs juniors.

Nous définissons d'abord une classe pour gérer le fonctionnement de mysql

class Database:
 aurl = '127.0.0.1'
 user = 'root'
 password = 'root'
 db = 'testdb'
 charset = 'utf8'

 def init(self):
  self.connection = MySQLdb.connect(self.aurl, self.user, self.password, self.db, charset=self.charset)
  self.cursor = self.connection.cursor()

 def insert(self, query):
  try:
   self.cursor.execute(query)
   self.connection.commit()
  except Exception, e:
   print e
   self.connection.rollback()

 def query(self, query):
  cursor = self.connection.cursor(MySQLdb.cursors.DictCursor)
  cursor.execute(query)
  return cursor.fetchall()

 def del(self):
  self.connection.close()

Ce code a été vu dans plusieurs de mes scripts précédents, impliquant des opérations Python Je vais écrire cette classe dans les scripts de la base de données mysql , y a-t-il donc un problème avec cette classe ?
La réponse est : Oui !

Cette classe est défectueuse et peut facilement provoquer une injection SQL. Parlons de la raison pour laquelle l'injection SQL se produit.

Afin de vérifier l'authenticité du problème, voici une méthode pour appeler la méthode dans la classe ci-dessus. Si une erreur se produit, une exception sera lancée directement.

def test_query(articleurl):
 mysql = Database()
 try:
  querySql = "SELECT * FROM `article` WHERE url='" + articleurl + "'"
  chanels = mysql.query(querySql)
  return chanels
 except Exception, e:
  print e

Cette méthode est très simple. L'une des instructions select query les plus courantes utilise également l'épissage de chaîne le plus simple pour former une instruction SQL. Il est évident que le paramètre articleurl transmis. est contrôlable, si vous souhaitez effectuer des tests d'injection, il vous suffit d'ajouter des guillemets simples après la valeur de articleurl pour effectuer des tests d'injection SQL. Pas grand chose à dire, il doit y avoir une vulnérabilité d'injection. Exécutez le script et voyez quels sont les résultats. sont

(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''t.tips''' at line 1")

L'erreur d'écho est très familière. Les paramètres de test que j'ai transmis ici sont

t.tips'

Ce qui suit est une autre situation qui conduit à l'injection après avoir légèrement modifié la méthode ci-dessus.

def test_query(articleurl):
 mysql = Database()
 try:
  querySql = ("SELECT * FROM `article` WHERE url='%s'" % articleurl)
  chanels = mysql.query(querySql)
  return chanels
 except Exception, e:
  print e

Cette méthode n'utilise pas directement la concaténation de chaînes, mais utilise %s pour remplacer les paramètres à transmettre. Ressemble-t-elle beaucoup à du SQL précompilé ? Cette façon d’écrire peut-elle empêcher l’injection SQL ? Après un test, vous saurez que l'écho suivant

(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''t.tips''' at line 1")

est le même que le résultat du test ci-dessus, donc cette méthode n'est pas possible, et cette méthode n'est pas une instruction SQL pré-compilée, alors que peut-on être fait pour empêcher l'injection de SQL Tissu en laine ?

Solution

Deux solutions

1> les paramètres d'entrée

2> Utilisez la méthode fournie avec le module MySQLdb de Python

La première solution se trouve en fait dans de nombreuses méthodes anti-injection PHP. Elle effectue une manipulation de caractères spéciaux sur les caractères spéciaux Escape. ou filtre.

La deuxième option consiste à utiliser des méthodes internes, similaires à PDO en PHP. Ici, vous pouvez simplement modifier la classe de base de données ci-dessus.

Code modifié

class Database:
 aurl = '127.0.0.1'
 user = 'root'
 password = 'root'
 db = 'testdb'
 charset = 'utf8'

 def init(self):
  self.connection = MySQLdb.connect(self.aurl, self.user, self.password, self.db, charset=self.charset)
  self.cursor = self.connection.cursor()

 def insert(self, query, params):
  try:
   self.cursor.execute(query, params)
   self.connection.commit()
  except Exception, e:
   print e
   self.connection.rollback()

 def query(self, query, params):
  cursor = self.connection.cursor(MySQLdb.cursors.DictCursor)
  cursor.execute(query, params)
  return cursor.fetchall()

 def del(self):
  self.connection.close()

Ici, exécutez des passes dans deux paramètres lors de l'exécution. Le premier est l'instruction SQL paramétrée, et le second est la valeur réelle du paramètre correspondante, la fonction . traitera la valeur du paramètre entrant en conséquence pour empêcher l'injection SQL. La méthode réelle utilisée est la suivante

preUpdateSql = "UPDATE `article` SET title=%s,date=%s,mainbody=%s WHERE id=%s"
mysql.insert(preUpdateSql, [title, date, content, aid])

De cette façon, vous pouvez empêcher l'injection SQL, après avoir transmis une liste, le module MySQLdb le fera en interne. sérialisez la liste dans un tuple, puis effectuez l'opération d'échappement.

[Recommandations associées]

1. Tutoriel vidéo gratuit de Python

2 Tutoriel d'introduction de base de Python

3. Tutoriel vidéo Python de la Geek Academy

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn