0%

Daten sicher ändern

Text, der wie SQL aussieht, als Daten behandeln

Ein Inventarkennzeichen darf einen Apostroph enthalten. Es kann sogar Text enthalten, der SQL ähnelt. Deine Funktion find_item soll nach diesem vollständigen Text als einem Wert suchen, ohne dass Satzzeichen die Abfrage umschreiben.

Betrachte diesen exakten Aufruf:

find_item(connection, "X' OR 1=1 --")

Der Wert sieht ungewöhnlich aus, aber die Funktion verwendet weiterhin dieselbe Anweisung und dasselbe Tupel mit einem Element:

TeilWas SQLite erreicht
SQL-AnweisungWHERE asset_tag = ?
Separate Werte("X' OR 1=1 --",)
ErgebnisNone
Anzahl der Gegenstände danachunverändert

SQLite behandelt jedes Zeichen innerhalb des gebundenen Wertes als Daten für die eine Position ?. Apostroph, Leerzeichen, Gleichheitszeichen und Bindestriche werden nicht zu SQL-Struktur. Kein gespeichertes Kennzeichen entspricht dem vollständigen Wert, also gibt die Suche None zurück.

Die unsichere Grenze entsteht, wenn ein Programm Anweisungstext aus einem veränderlichen Wert aufbaut. Ein f-String hat etwa diese Form:

statement = f"... WHERE asset_tag = '{asset_tag}'"

Hier wird der Wert in die Anweisung eingefügt, bevor SQLite sie liest. Ein Apostroph kann den Wert in Anführungszeichen vorzeitig beenden, und die übrigen Zeichen können als SQL interpretiert werden. Wenn benutzergesteuerter Text die Struktur einer Anweisung verändert, besteht ein Risiko für SQL-Injection.

Parameterbindung vermeidet dieses Risiko bei Werten, weil Anweisung und Werte als separate Argumente übergeben werden. Repariere Apostrophe nicht von Hand und entferne keine Satzzeichen aus dem eingegebenen Text. Behalte den vollständigen Wert bei und lass die Datenbankschnittstelle ihn binden.

Hier ist diese sichere Grenze als vollständiger Aufruf:

connection.execute(
    "SELECT id FROM items WHERE asset_tag = ?",
    (asset_tag,),
)

Platzhalter sind kein allgemeines Ersetzungssystem. Ein ? kann dort stehen, wo SQL einen Wert erwartet, etwa ein Inventarkennzeichen oder eine Leihdauer. Es kann nicht für einen Tabellennamen, Spaltennamen, Operator oder ein Schlüsselwort stehen. Diese Teile bestimmen die Struktur der Anweisung und bleiben in deinem Programm fest.

Welcher Aufruf hält das veränderliche Inventarkennzeichen als Daten getrennt und lässt die SQL-Struktur unverändert?

Die sichere Regel ist angenehm kurz: Halte SQL fest, lass veränderliche Werte vollständig und übergib diese Werte separat.