Heim  >  Artikel  >  Backend-Entwicklung  >  Einführung in die Verhinderung der SQL-Injection in Python

Einführung in die Verhinderung der SQL-Injection in Python

巴扎黑
巴扎黑Original
2017-08-18 17:05:561599Durchsuche

Vorwort

Die größte Web-Schwachstelle ist SQL. Unabhängig davon, welche Sprache für die Web-Back-End-Entwicklung verwendet wird, kann es zu SQL-Injection-Angriffen kommen, solange eine relationale Datenbank verwendet wird. Wie tritt also die SQL-Injection während der Python-Webentwicklung auf und wie lässt sich dieses Problem lösen?

Natürlich möchte ich nicht diskutieren, wie andere Sprachen die SQL-Injection verhindern. Es gibt verschiedene Methoden zur PHP-Injection-Prävention. Hier werde ich ein Beispiel geben.

Ursache

Die häufigste Ursache der Sicherheitslücke ist das String-Splicing. Natürlich handelt es sich bei der SQL-Injection nicht nur um das Splicing, es gibt auch Dinge wie Wide-Byte-Injection und das Entkommen von Sonderzeichen Es gibt viele Arten, aber hier werden wir über die häufigste String-Verkettung sprechen, die auch der häufigste Fehler für junge Programmierer ist.

Zuerst definieren wir eine Klasse zur Abwicklung von MySQL-Operationen

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. Sprechen wir darüber, 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(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-Abfrageanweisungen verwendet auch das einfachste String-Splicing, um eine SQL-Anweisung zu bilden. Es ist offensichtlich, dass der übergebene Parameter testUrl steuerbar ist Um einen Injektionstest durchzuführen, müssen Sie nach dem Wert von testUrl nur ein einfaches Anführungszeichen hinzufügen, um den SQL-Injektionstest durchzuführen. Es ist unnötig zu erwähnen, dass eine Injektionsschwachstelle vorhanden ist und das Ergebnis angezeigt wird >(1064, „Sie haben einen Fehler in Ihrer SQL-Syntax; überprüfen Sie das Handbuch, das Ihrer MariaDB-Serverversion entspricht, um die richtige Syntax für die Verwendung in der Nähe von „t.tips“ in Zeile 1 zu finden.)

Die Fehlermeldung wird angezeigt, es kommt mir bekannt vor. Fehler, die Testparameter, die ich hier übergeben habe, sind

t.tips'

Lassen Sie uns über eine andere Situation sprechen, die zur Injektion führt, nachdem wir das oben Gesagte leicht modifiziert haben Methode

Diese Methode verwendet keine direkte Zeichenfolgenverkettung, sondern verwendet %s, um die zu übergebenden Parameter zu ersetzen. Sieht sie sehr nach vorkompiliertem SQL aus? Kann diese Schreibweise die SQL-Injection verhindern? Nach dem Testen werden Sie es wissen. Die Antwort lautet wie folgt:
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

(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?

Lösung

Zwei Lösungen

1> Kodieren und maskieren Sie die eingehenden Parameter

2> Verwenden Sie die Methode, die mit dem MySQLdb-Modul von Python geliefert wird

Die erste Lösung ist tatsächlich in vielen PHP-Anti-Injection-Methoden enthalten und besteht darin, Sonderzeichen zu maskieren oder zu 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

Hier übergibt die Ausführung bei der Ausführung zwei Parameter, der erste ist die parametrisierte SQL-Anweisung und der zweite ist der entsprechende tatsächliche Parameterwert. Die Funktion verarbeitet die übergebenen Parameter Parameterwert entsprechend, um SQL-Injection zu verhindern. Die tatsächlich verwendete Methode ist wie folgt:
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()

preUpdateSql = "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 wird das MySQLdb-Modul intern in die Liste serialisiert ein Tupel, und dann wird die Escape-Operation ausgeführt.

Das obige ist der detaillierte Inhalt vonEinführung in die Verhinderung der SQL-Injection in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn