La vulnérabilité Web numéro un est SQL. Quel que soit le langage utilisé pour le développement back-end Web, tant qu'une base de données relationnelle est utilisée, des attaques par injection SQL peuvent être rencontrées. 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 méthodes pour empêcher l'injection en PHP sur Internet. La méthode de Python est en fait similaire. Ici, je vais donner un exemple. .
La cause la plus courante des vulnérabilités est l'épissage de chaînes. Bien sûr, l'injection SQL n'est pas seulement un cas d'épissage, mais aussi l'injection d'octets larges et l'échappement de caractères spéciaux. , mais nous parlerons ici de la concaténation de chaînes la plus courante, qui est également l'erreur la plus courante pour les programmeurs débutants.
Nous définissons d'abord une classe pour gérer les opérations MySQL
class Database: hostname = '127.0.0.1' user = 'root' password = 'root' db = 'pythontab' charset = 'utf8' def __init__(self): self.connection = MySQLdb.connect(self.hostname, 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()
Y a-t-il 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, écrivez ici une méthode pour appeler la méthode de la classe ci-dessus. Si une erreur se produit, une exception sera levée directement.
def test_query(testUrl): mysql = Database() try: querySql = "SELECT * FROM `article` WHERE url='" + testUrl + "'" chanels = mysql.query(querySql) return chanels except Exception, e: print e
Cette méthode est très simple. L'une des instructions de requête de sélection les plus courantes utilise également la concaténation de chaînes la plus simple pour former une instruction SQL. Il est évident que le paramètre testUrl transmis est contrôlable si vous le souhaitez. pour effectuer des tests d'injection, il vous suffit d'ajouter un guillemet simple après la valeur de testUrl pour effectuer le test d'injection SQL. Inutile de dire qu'il doit y avoir une vulnérabilité d'injection. Exécutez le script et voyez quel est le résultat
<🎜. >(1064, "Vous avez une erreur dans votre syntaxe SQL ; consultez le manuel qui correspond à la version de votre serveur MariaDB pour connaître la bonne syntaxe à utiliser près de ''t.tips''' à la ligne 1") Le message d'erreur s'affiche, il semble familier Erreur, les paramètres de test que j'ai transmis ici sont t.tips'Parlons d'une autre situation qui conduit à l'injection Après avoir légèrement modifié ce qui précède. methoddef test_query(testUrl): mysql = Database() try: querySql = ("SELECT * FROM `article` WHERE url='%s'" % testUrl) chanels = mysql.query(querySql) return chanels except Exception, e: print e
Ici, exécutez des passes dans deux paramètres lors de l'exécution. Le premier est l'instruction SQL paramétrée et la seconde est la valeur réelle du paramètre correspondante, la fonction traitera le. a transmis la valeur du paramètre en conséquence pour empêcher l'injection SQL. La méthode réelle utilisée est la suivante
class Database: hostname = '127.0.0.1' user = 'root' password = 'root' db = 'pythontab' charset = 'utf8' def __init__(self): self.connection = MySQLdb.connect(self.hostname, 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()
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!