Die Web-Schwachstelle Nummer eins ist keine andere als SQL. Unabhängig davon, welche Sprache für die Web-Backend-Entwicklung verwendet wird, solange eine relationale Datenbank verwendet wird, ist SQL Injektionsangriffe können fraglich sein. Wie tritt also die SQL-Injection während des Python-Webentwicklungsprozesses auf und wie lässt sich dieses Problem lösen?
Natürlich möchte ich nicht diskutieren, wie andere Sprachen die Injektion in PHP im Internet verhindern können eigentlich ähnlich, hier Lassen Sie mich Ihnen ein Beispiel geben.
Die häufigste Ursache der Schwachstelle ist das String-Spleißen. Natürlich ist SQL-Injection nicht nur Spleißen, es gibt auch Dinge wie Wide Bytes. Es gibt viele Arten der Injektion, Sonderzeichen Escapezeichen usw. Hier werden wir über das häufigste String-Spleißen sprechen, das auch der häufigste Fehler für junge Programmierer ist.
Zuerst definieren wir eine Klasse, die den Betrieb von MySQL abwickelt
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()
Gibt es ein Problem mit dieser Klasse?
Die Antwort lautet: Ja!
Diese Klasse ist fehlerhaft und kann leicht eine SQL-Injection verursachen. Lassen Sie uns darüber sprechen, warum SQL-Injection auftritt.
Um die Authentizität des Problems zu überprüfen, finden Sie hier eine Methode zum Aufrufen der Methode in der obigen Klasse. Wenn ein Fehler auftritt, wird direkt eine Ausnahme ausgelöst .
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
Diese Methode ist sehr einfach. Eine der häufigsten select-Abfragen-Anweisungen verwendet auch die einfachste Zeichenfolgenverkettung, um eine SQL-Anweisung zu bilden. Es ist offensichtlich, dass der Parameter testUrl übergeben wird Wenn Sie einen Injektionstest durchführen möchten, müssen Sie nach dem Wert von testUrl nur ein einfaches Anführungszeichen hinzufügen, um einen SQL-Injektionstest durchzuführen. Führen Sie das Skript aus und prüfen Sie, was passiert Ergebnis ist
(1064, „Sie haben einen Fehler in Ihrer SQL-Syntax; überprüfen Sie das Handbuch, das Ihrer MariaDB-Serverversion entspricht für die rightSyntax zur Verwendung in der Nähe von „t.tips“ in Zeile 1“)
zeigt einen Fehler an, einen sehr bekannten Fehler. Der Testparameter, den ich hier übergeben habe, ist
t.tips'
Sprechen wir über eine andere Situation, die zur Injektion führt, nachdem wir die obige Methode leicht modifiziert haben
def 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
Diese Methode verwendet nicht direkt String-Splicing, sondern %s der Übergabe sehen die Parameter sehr nach vorkompiliertem SQL aus? Kann diese Schreibweise die SQL-Injection verhindern? Nach dem Testen werden Sie es wissen. Die Antwort lautet wie folgt:
(1064, „Sie haben einen Fehler in Ihrer SQL-Syntax; überprüfen Sie das Handbuch, das Ihrer MariaDB-Serverversion entspricht, um die richtige Syntax zu verwenden“ t.tips' '' in Zeile 1")
Die Ergebnisse sind die gleichen wie beim obigen Test, daher ist diese Methode nicht möglich und diese Methode ist keine vorkompilierte SQL-Anweisung. Was kann also getan werden, um dies zu verhindern? SQL-Injektion?
Zwei Lösungen
1> Kodierung und Escapezeichen der eingehenden Parameter
2> Verwenden Sie die Methode, die mit dem MySQLdb-Modul geliefert wird.
Die erste Lösung ist tatsächlich in vielen PHP-Anti-Injection-Methoden zu finden.
Die zweite Möglichkeit besteht darin, interne Methoden zu verwenden, ähnlich wie PDO in PHP. Hier können Sie einfach die Datenbankklasse oben ändern.
Geänderter Code
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()
Hier werden bei der Ausführung zwei Parameter übergeben. Der erste ist die parametrisierte SQL-Anweisung tatsächlicher Parameterwert. Die -Funktion verarbeitet den eingehenden Parameterwert entsprechend, um die SQL-Injection zu verhindern. Die tatsächlich verwendete Methode ist wie folgt:
preUp dateSql = "UPDATE `article` SET title=%s,date=%s,mainbody=%s WHERE id=%s"
mysql.insert(preUpdateSql , [Titel, Datum, Inhalt, Hilfe])
Dies kann die SQL-Injection verhindern. Nach der Übergabe einer Liste serialisiert das MySQLdb-Modul die Liste intern in ein Tupel und führt dann einen Escape-Vorgang aus.
Das obige ist der detaillierte Inhalt vonSo verhindern Sie die SQL-Injection mit Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!