Einführung
Die Suche eines kleinen Outdoor-Shops soll nur gelistete Produkte mit exakt passendem Namen liefern. Ein Fehler beim Aufbau der Abfrage lässt die Eingabe diese Regel ändern; sogar ein normaler Apostroph stört die Suche. Du verfolgst echte Anfragen, reparierst eine kurze Python-Funktion und prüfst Sicherheit und nützliche Ergebnisse.
Workstation, App Server und Shop Web sind vorbereitet. Grundlegende Terminalbedienung und Tabwechsel reichen aus. SQL, die nötige Python-Syntax und Editorbedienung werden hier eingeführt. Die Daten sind synthetisch; HTTP-Dienst und SQLite-Verarbeitung sind echt.
Eine normale Produktsuche ausführen
In diesem Schritt benutzt du den Shop und ordnest ein Ergebnis seiner Datenbankzeile zu. Du hilfst einem kleinen Outdoor-Shop, seine Suche zu reparieren. Sie darf nur gelistete Produkte liefern, deren Namen exakt zur Eingabe passen. Alle Produkte und Preise sind synthetische Übungsdaten.
Wähle zu Beginn dieses Schritts den Tab Shop Web in der Lab-Oberfläche aus.
Eine Tabelle speichert Datensätze als Zeilen; benannte Spalten beschreiben sie. Hier siehst du die vorbereitete Tabelle products. listed ist bei öffentlichen Produkten 1, bei internen Prototypen 0. Preise sind ganze Einheiten einer Übungswährung.
| id | name | price | listed |
|---|---|---|---|
| 1 | Trail Mug | 18 | 1 |
| 2 | Camper's Cup | 22 | 1 |
| 3 | Prototype Mug | 99 | 0 |
| 4 | ORANGE Bowl | 12 | 1 |
Wechsle zum Tab Shop Web. Gib unter Product name den Wert Trail Mug ein und wähle Search. rows sollte [1, "Trail Mug", 18] enthalten und error auf null stehen (kein Fehler). Die Seite sendet eine Anfrage an die Python-App. Diese fragt SQLite nach passenden Datensätzen und liefert das Ergebnis zurück. Seite, Anwendungscode und Datenbank sind unterschiedliche Teile dieses Anfragewegs.

Eine Abfrage stellt der Datenbank eine Frage. Die lokale Lehrspur zeigt das von SQLite ausgeführte SQL:
SELECT id, name, price FROM products WHERE listed = 1 AND name = 'Trail Mug' ORDER BY id
SELECT nennt die zurückgegebenen Spalten, FROM die Tabelle. WHERE begrenzt die Zeilen. AND verlangt beide Bedingungen: gelistet und exakter Name. Einfache Anführungszeichen begrenzen einen SQL-Textwert. ORDER BY id sorgt für eine stabile Reihenfolge. Die Seite gibt listed nicht zurück, doch die Abfrage filtert weiterhin danach.
Das Terminal Workstation ist der Client zum Senden von Anfragen. App Server öffnet das App-Verzeichnis für die spätere Reparatur. Es sind unabhängige Sitzungen auf demselben Übungsrechner, keine getrennten Maschinen. Die Seite zeigt diese Beziehung und wird von der laufenden App bereitgestellt.
Wechsle zum Tab Workstation, um dieselbe Anfrage zu senden:
Wechsle zum Tab Workstation, bevor du den folgenden Befehl ausführst.
python3 probe.py "Trail Mug"
python3 startet den vorbereiteten Client probe.py. Sein einziges Argument ist der Suchtext. Doppelte Anführungszeichen halten einen Namen mit Leerzeichen als ein Argument zusammen; die Shell entfernt diese äußeren Zeichen. Der Client kodiert den Wert sicher in eine HTTP-Anfrage, das Anfrageformat der Web-App. 127.0.0.1 bezeichnet hier denselben Übungsrechner.
Lies rows, trace und error in der JSON-Ausgabe. JSON ist die strukturierte Antwort: Arrays verwenden eckige Klammern, null bedeutet kein Fehler. Wenn die Seite keine Verbindung bekommt, lade Shop Web neu. Ein Verbindungsfehler unterscheidet sich von einer erfolgreichen Suche ohne Treffer. Die Prüfung liest das echte Anfrageergebnis; ein Bericht ist unnötig.
Beobachten, wie Eingaben die Abfrage ändern
In diesem Schritt beobachtest du einen begrenzten SQL-Injection-Test im Übungsshop. SQL-Injection bedeutet, dass Eingaben die Struktur einer Abfrage verändern, statt Textwerte zu bleiben. Verwende diese Tests nur im vorbereiteten Lab.
Wähle zu Beginn dieses Schritts den Tab Workstation in der Lab-Oberfläche aus.
Wechsle zum Tab App Server. Lies die kurze Funktion mit cat, das eine Datei ohne Bearbeitung ausgibt:
Wechsle zum Tab App Server, bevor du den folgenden Befehl ausführst.
cat query.py
def search(db, text): definiert die Funktion. db ist die offene Datenbankverbindung, text der empfangene Wert. Die eingerückten Zeilen bilden den Funktionskörper. sql = weist einer Variablen eine Python-Zeichenkette zu. Doppelte Anführungszeichen begrenzen diese Zeichenkette, die einfachen darin den SQL-Text. + text + verkettet den Benutzerwert direkt mit SQL. db.execute(sql) lässt SQLite die Abfrage ausführen; fetchall() sammelt Ergebniszeilen, return gibt sie zurück.
Wechsle zum Tab Workstation und sende exakt diesen Wert, einschließlich des Leerzeichens nach den beiden Bindestrichen:
Wechsle zum Tab Workstation, bevor du den folgenden Befehl ausführst.
python3 probe.py "' OR 1=1 -- "
Die äußeren doppelten Anführungszeichen gehören zur Shell. Das erste einfache Anführungszeichen erreicht SQLite und schließt den leeren Textwert der verketteten Abfrage. OR erlaubt eine der Bedingungen; 1=1 ist immer wahr. -- beginnt einen Kommentar, wodurch das ursprüngliche Schlusszeichen und die Sortierung ignoriert werden. Die Spur enthält jetzt:
SELECT id, name, price FROM products WHERE listed = 1 AND name = '' OR 1=1 -- ' ORDER BY id
Du siehst alle vier Zeilen, darunter [3, "Prototype Mug", 99]. Dieser Prototyp ist nicht gelistet. Die Anfrage überschritt also die Geschäftsgrenze, obwohl sie nur Daten las. Eine erfolgreiche HTTP-Antwort beweist keine sichere Suche.
Versuche nun einen gültigen Namen mit Apostroph:
python3 probe.py "Camper's Cup"
Die verwundbare App liefert rows: [], eine leere trace und error mit near "s": syntax error. SQLite konnte das fehlerhafte SQL nicht ausführen; daher gibt es keine abgeschlossene Abfrage zum Anzeigen. Dieser Fehler ist erwartet. Der Client beendet sich normal, damit du fortfahren kannst.
Ein Apostroph ist ein gültiger Teil eines Produktnamens. Entfernen würde den gewünschten Namen verändern; das Ablehnen aller solchen Eingaben würde Kunden abweisen. Ein Wortfilter für OR würde außerdem ORANGE Bowl beschädigen. Die Reparatur muss den Wert erhalten und von der SQL-Struktur trennen.
Den Suchwert binden
In diesem Schritt reparierst du die Funktion und erhältst Spalten, exakten Vergleich, Listungsregel und Sortierung. Wechsle zum Tab App Server.
Wähle zu Beginn dieses Schritts den Tab App Server in der Lab-Oberfläche aus.
Eine parametrisierte Abfrage trennt SQL-Struktur und Werte. In Pythons SQLite-API markiert ? eine Wertposition. Übergib den Wert separat an execute; setze den Platzhalter nicht in Anführungszeichen und verkette den Wert nicht mit SQL. db.execute("SELECT ?", (text,)) liefert etwa den Text als Daten zurück, ohne ihn als SQL zu interpretieren.
(text,) ist ein Tupel mit einem Element, eine geordnete Parametersammlung. Das abschließende Komma macht es zum Tupel; (text) allein ist nur der Wert in Klammern. Die äußeren Klammern von execute(sql, (text,)) rufen eine Funktion mit zwei Argumenten auf: SQL-Vorlage und Wertetupel. Der Datenbanktreiber bindet den Wert an den Platzhalter.
Öffne die vorbereitete Datei im Terminaleditor:
Wechsle zum Tab App Server, bevor du den folgenden Befehl ausführst.
nano query.py
Bewege dich mit Pfeiltasten, lösche mit Backspace/Delete und tippe zum Bearbeiten. Ersetze die beiden eingerückten Zeilen mit sql = und return, sodass die Funktion exakt so aussieht:
def search(db, text):
sql = "SELECT id, name, price FROM products WHERE listed = 1 AND name = ? ORDER BY id"
return db.execute(sql, (text,)).fetchall()
Lass vier Leerzeichen vor jeder Körperzeile und keine vor def. Python gruppiert den Körper durch Einrückung. Speichere mit Ctrl+O, bestätige query.py mit Enter und beende mit Ctrl+X. Der ursprüngliche Kommentar darf bleiben.
Die App liest und kompiliert query.py bei jeder Anfrage neu. Speichern reicht; ein Neustart ist unnötig. Ein ungespeicherter Puffer wirkt sich nicht aus. Tipp- oder Einrückungsfehler erscheinen im Feld error der nächsten Antwort. Öffne dieselbe Datei erneut, korrigiere, speichere und sende die Anfrage wieder.
Wechsle zum Tab Workstation und wiederhole beide Werte:
Wechsle zum Tab Workstation, bevor du den folgenden Befehl ausführst.
python3 probe.py "Camper's Cup"
python3 probe.py "' OR 1=1 -- "
Das echte Produkt liefert jetzt [2, "Camper's Cup", 22], der spezielle Test rows: []. Beide haben error: null. Diese Datenbank enthält kein Produkt mit exakt diesem speziellen Namen.
Die Spur kann Camper''s Cup oder den gesamten speziellen Text in Anführungszeichen zeigen. SQLite zeigt erweitertes SQL nach der Bindung, einschließlich maskierter Werte, nicht die ursprüngliche Vorlage. Werte in der Spur bedeuten keine Python-Verkettung: In query.py siehst du Vorlage und getrenntes Tupel. Ersetze gebundene Parameter nicht durch selbst geschriebenes Maskieren.
Die Geschäftssuche erhalten
In diesem Schritt prüfst du Sicherheit und normale Funktion gemeinsam. Eine abgeschaltete Suche oder eine fest eingebaute leere Antwort könnte den Prototyp verstecken, würde aber Kunden am Finden von Produkten hindern.
Wähle zu Beginn dieses Schritts den Tab Workstation in der Lab-Oberfläche aus.
Wechsle zum Tab Workstation. Sende erneut den normalen Namen:
Wechsle zum Tab Workstation, bevor du den folgenden Befehl ausführst.
python3 probe.py "Trail Mug"
Du solltest weiterhin [1, "Trail Mug", 18] erhalten. Prüfe, dass ein gültiges Wort mit OR nicht abgelehnt wird:
python3 probe.py "ORANGE Bowl"
Erwarte [4, "ORANGE Bowl", 12]. Suche den nicht gelisteten Prototyp nach seinem normalen Namen:
python3 probe.py "Prototype Mug"
Erwarte rows: [] und error: null. Die Bindung verhindert Injection; die unveränderte Bedingung listed = 1 bestimmt weiterhin öffentliche Produkte. Diese Bedingung bei der Reparatur zu entfernen wäre unsicher.
Wechsle zurück zum Tab Shop Web, gib Camper's Cup ein und wähle Search. Bestätige die Ergebniszeile. Wiederhole mit ' OR 1=1 -- und bestätige ein leeres Ergebnis ohne Fehler. Browser und Client verwenden dieselbe Abfragefunktion.

Starte die Abschlussprüfung des Schritts. Sie sendet reine Leseanfragen und führt deine unveränderte Funktion mit zusätzlichen synthetischen Zeilen in einer kurzlebigen Speicherdatenbank aus. So werden exakter Vergleich, Satzzeichen, Listungsregeln und unbekannte Namen geprüft, ohne die aktive Datenbank zu bearbeiten. Auch ein SQL-ähnlicher Produktname muss als normale Daten auffindbar bleiben, wenn er exakt existiert und gelistet ist.
Falls eine Prüfung scheitert, wechsle zurück zum Tab App Server, öffne query.py erneut und vergleiche Platzhalter, Tupelkomma, Einrückung und Geschäftsregel mit der Reparatur. Speichere und teste erneut. Lass Datenbank, Client und Serverrahmen unverändert; veränderte Datensätze oder feste Antworten reparieren die Abfrage nicht.
Zusammenfassung
Du hast eine Suche von der Seite bis zu einer echten SQLite-Abfrage verfolgt, Strukturänderungen durch Eingaben gesehen und den Python-Aufruf mit Platzhalter und Einwerttupel repariert. Du prüftest normale Namen, Apostrophe, den begrenzten Test und die erhaltene Listungsregel. Die Bestell-Challenge überträgt diese Trennung auf ein anderes Geschäftsobjekt.


