Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

SQL-Injection verhindern mit Parametern

Nach dieser Lektion: Ich kann eine Abfrage schreiben, in die eingetippter Text nur als Parameter gelangt.

Lektion, 60 Min.3 BefehleSQL-Injection-Lab: eine schwache Shop-Suche angreifen, die Abfrage reparieren und die Reparatur belegen

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

BegriffWas er bedeutet
Abfrageeine Frage, die ein Programm an eine Datenbank stellt; auf Englisch Query
Parameterein Wert, der neben der Abfrage gesendet wird und nie in ihr steht
Platzhalterdas Zeichen ? an der Stelle, an die ein Parameter kommt
ZusammensetzenText mit + verbinden; bei Abfragen die Quelle der Lücke
Erlaubnislistedie 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

Code: python
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?

Befehl
docker exec app grep -c "+ term +" /tmp/app/app.py

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

Befehl
docker exec app grep -c "execute(" /tmp/app/app.py

Hier 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

Befehl
curl -s -G --data-urlencode "q=Baker's" http://app:8000/search

Hier 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

Code: python
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.

Über dieses Lab und seinen Quellcode: SQL-Injection-Lab: eine schwache Shop-Suche angreifen, die Abfrage reparieren und die Reparatur belegen

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.