Wie verhindert man SQL-Injection im Code?
SQL-Injection verhindern Sie, indem Sie Werte nie in den Text einer Abfrage schreiben, sondern als Parameter neben der Abfrage senden. Das ist wichtig, weil eine zusammengesetzte Abfrage dem Besucher erlaubt, einen Teil davon selbst zu schreiben.
Diese Lektion zeigt, wie Sie die sichere Form schreiben und wie Sie eine Abfrage bauen, deren Teile sich ändern.
Am Ende dieser Lektion
Notiz
Ich kann eine Abfrage schreiben, in die eingetippter Text nur als Parameter gelangt.
Schlüsselwörter
| Begriff | Was er bedeutet |
|---|---|
| Abfrage | eine Frage, die ein Programm an eine Datenbank stellt; auf Englisch Query |
| Parameter | ein Wert, der neben der Abfrage gesendet wird und nie in ihr steht |
| Platzhalter | das Zeichen ? an der Stelle, an die ein Parameter kommt |
| Zusammensetzen | Text mit + verbinden; bei Abfragen die Quelle der Lücke |
| Erlaubnisliste | die Werte, die gelten; für Namen, die kein Parameter sein können |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Zusammensetzen und Parameter sind zwei Wege
Beim Zusammensetzen verbindet das Programm einen festen Anfang mit dem Text des Besuchers. Die Datenbank liest alles als eine Abfrage.
Beim Parameter steht in der Abfrage nur ein ?. Den Wert schickt das Programm getrennt. Die Datenbank legt zuerst die Form der Abfrage fest. Danach kann der Wert nur noch ein Wert sein.
Dieselbe Suche, sicher geschrieben
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE artikel (name TEXT, preis REAL)")
db.execute("INSERT INTO artikel VALUES (?, ?)", ("Lampe", 18.0))
db.execute("INSERT INTO artikel VALUES (?, ?)", ("Tasse", 6.0))
def suche(begriff):
sql = "SELECT name, preis FROM artikel WHERE name LIKE ?"
return db.execute(sql, ("%" + begriff + "%",)).fetchall()
# Ändern Sie den Begriff in "a", dann in "x' OR 1=1 --".
print(suche("Tas"))
Die Zeile im Shop, die verbindet
Der Shop des Labs setzt seine Suche durch Zusammensetzen. Die beiden Runs zählen nur: wie viele Zeilen das Programm so verbinden, und wie viele Datenbankaufrufe es hat. Der dritte sucht einen Namen mit Apostroph und zeigt, wie die Abfrage reißt.
Sie ändern noch nichts. Lesen Sie die Zahlen als Fragen: Welcher Aufruf ist der verdächtige?
Die eine Regel
Warnung
Dieses Lab ist ein Shop, der absichtlich unsicher ist. Greifen Sie nur Ihre eigene, private Kopie an und nichts sonst. Sie hat keine Verbindung ins Internet. Dieselben Versuche bei einem fremden System sind eine Straftat.
Wie oft verbindet das Programm Text?
docker exec app grep -c "+ term +" /tmp/app/app.pyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Wie viele Datenbankaufrufe hat es?
docker exec app grep -c "execute(" /tmp/app/app.pyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Ein Name mit Apostroph
curl -s -G --data-urlencode "q=Baker's" http://app:8000/searchHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Spaltennamen und Sortierung sind keine Parameter
Ein Parameter steht nur für einen Wert. Ein Spaltenname oder eine Sortierung muss im Text der Abfrage stehen. Hier hilft eine Erlaubnisliste: Das Programm wählt aus eigenen Wörtern, nie aus dem Text des Besuchers.
Dasselbe gilt, wenn Filter dazukommen. Jeder Teil der Abfrage stammt aus dem Programm, jeder Wert wird ein Parameter.
Eine Abfrage mit wählbarer Sortierung
SORTIERUNG = ["name", "preis"]
def baue(wunsch):
spalte = "name"
if wunsch in SORTIERUNG:
spalte = wunsch
sql = "SELECT name, preis FROM artikel ORDER BY " + spalte
return sql
# Probieren Sie "preis", dann "preis; DROP TABLE artikel".
print(baue("preis"))
Ein häufiger Fehler
Warnung
Viele glauben, Anführungszeichen zu ersetzen schütze eine zusammengesetzte Abfrage. Das stimmt nicht: Ein Filter vergisst Fälle, etwa Zahlen ohne Anführungszeichen. Ein Parameter wirkt, weil er den Wert nie in die Abfrage mischt. Nutzen Sie ihn für jeden Wert.