Vorwort
Jeder sollte wissen, dass die größte Web-Schwachstelle mittlerweile SQL ist, egal welche Sprache für die Web-Back-End-Entwicklung verwendet wird, solange es sich um eine relationale handelt Wenn eine Datenbank verwendet wird, kann es zu Problemen mit SQL-Injection-Angriffen kommen. Wie sieht die SQL-Injection während der Python-Webentwicklung aus und wie lässt sich dieses Problem lösen?
Natürlich möchte ich nicht diskutieren, wie andere Sprachen die SQL-Injektion vermeiden. Es gibt verschiedene Möglichkeiten, die Injektion in PHP zu verhindern (Anmerkung des Bloggers: Es gilt als die großartigste Sprache der Welt ) im Internet, einschließlich Python. Die Methoden sind tatsächlich ähnlich, daher werde ich Ihnen hier ein Beispiel geben.
Ursache
Die häufigste Ursache der Schwachstelle ist das String-Splicing Es gibt auch viele Arten wie Wide-Byte-Injection, Sonderzeichen-Escape 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 zur Abwicklung von MySQL-Operationen
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()
Dieser Code wurde in vielen meiner vorherigen Skripte gesehen, an denen ich beteiligt war wird diese Klasse in Python-Skripte schreiben, die MySQL-Datenbanken betreiben. Gibt es also 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, schreiben Sie hier eine Methode, um die Methode in der obigen Klasse aufzurufen. Wenn ein Fehler auftritt, wird direkt eine Ausnahme ausgelöst.
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
Diese Methode ist sehr einfach und verwendet auch das einfachste String-Splicing, um eine SQL-Anweisung zu bilden dass der eingegebene Parameter „articleurl“ kontrollierbar ist. Wenn Sie einen Injektionstest durchführen möchten, müssen Sie nach dem Wert von „articleurl“ nur ein einfaches Anführungszeichen hinzufügen, um den SQL-Injektionstest durchzuführen. Führen Sie das Skript aus und sehen Sie, was die Ergebnisse sind.
(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")
Es ist ein sehr bekannter Fehler, den ich hier eingegeben habe sind
t.tips'
Lassen Sie uns über eine andere Situation sprechen, die zu einer Injektion führt, nachdem wir die obige Methode leicht modifiziert haben
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
Diese Methode verwendet keine direkte Zeichenfolgenverkettung, sondern %s, um die zu übergebenden Parameter zu ersetzen. Sieht es nicht sehr nach vorkompiliertem SQL aus? Kann diese Schreibweise die SQL-Injection verhindern? Nachdem Sie es getestet haben, werden Sie wissen, dass die Antwort wie folgt lautet:
(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")
ist das gleiche wie das obige Testergebnis, also diese Methode Dies ist nicht möglich und dies Die Methode besteht nicht darin, SQL-Anweisungen vorzukompilieren. Was kann also getan werden, um die SQL-Injektion zu verhindern?
Lösung
1> die Eingabeparameter
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 und führt eine Sonderzeichenmanipulation an Sonderzeichen durch oder filtern.
Die zweite Möglichkeit besteht darin, interne Methoden zu verwenden, ähnlich wie PDO in PHP. Hier können Sie einfach die obige Datenbankklasse ändern.
Geänderter Code
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()
Bei der Ausführung werden hier zwei Parameter übergeben. Der erste ist eine parametrisierte SQL-Anweisung Der zweite ist der entsprechende tatsächliche Parameterwert, der innerhalb der Funktion entsprechend verarbeitet wird, um die SQL-Injection zu verhindern. Die tatsächlich verwendete Methode ist wie folgt:
preUpdateSql = "UPDATE `article` SET title=%s,date=%s,mainbody=%s WHERE id=%s" mysql.insert(preUpdateSql, [title, date, content, aid])
Dies kann die SQL-Injection verhindern. Nach der Übergabe einer Liste serialisiert das MySQLdb-Modul die Liste in ein Tupel und führt dann die Escape-Operation aus.
Weitere verwandte Artikel zu Methoden zur Verhinderung der SQL-Injection in Python finden Sie auf der chinesischen PHP-Website!