Ein Gästebuch, das Notizen ausführt
Ein Shop baut ein Gästebuch in seine Seite ein. Besucher hinterlassen eine Notiz, alle lesen die Notizen auf einer Seite.
Ein Besucher schreibt keine Worte, sondern ein winziges Programm. Jeder spätere Besucher öffnet die Seite, und sein Browser führt es unbemerkt aus. Der Shop hat nichts davon geschrieben.
Die eine Regel
Warnung
Dieses Lab ist eine Website, die 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. Das gilt auch dann, wenn Sie nichts beschädigen wollen.
Am Ende dieser Lektion
Notiz
Ich kann verhindern, dass eine Seite Text ausführt, den ein Besucher getippt hat.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Cross-Site-Scripting | eine Seite, die Skript ausführt, das ein Besucher getippt hat | XSS |
| Skript | ein kleines Programm, das ein Browser in einer Seite ausführt | |
| Escapen | Sonderzeichen durch sicheren Text ersetzen; auch Maskieren | < wird zu < |
| Reflektiert | in einer Anfrage gesendet und sofort in der Antwort wieder gezeigt | |
| Gespeichert | von der Seite abgelegt und jedem späteren Besucher gezeigt | |
| Cookie | ein kleiner Wert, den der Browser behält und der Seite zurücksendet |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Getippter Text kann Teil der Seite werden
Ein Browser liest eine Seite als Text mit Tags darin. Ein <b>-Tag macht fett. Ein <script>-Tag führt ein Programm aus.
Setzt eine Seite den Text eines Besuchers unverändert ein, kann der Browser getippten Text nicht von den eigenen Tags der Seite unterscheiden. Skript, das ein Besucher getippt hat, läuft dann, als hätte die Seite es geschrieben.
Beispiel: reflektiert und gespeichert
| Reflektiert | Gespeichert | |
|---|---|---|
| Wohin der Text gelangt | In die Anfrage, dann sofort zurück in die Antwort | In die Datensätze der Seite, dann in spätere Seiten |
| Wen es trifft | Wer den präparierten Link öffnet | Jeden, der die Seite danach öffnet |
| Beispiel | Eine Suchseite, die schreibt: Sie suchten nach ... | Ein Gästebuch oder eine Produktbewertung |
| Warum gespeichert schlimmer ist | Eine Notiz erreicht viele, ohne dass jemand einen Link verschickt |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Die Website in Ihrem Lab
Ihr Lab betreibt die Website, die Sie testen werden. Starten Sie sie und führen Sie dann diese drei Befehle aus. Sie sehen nur die Anmeldeseite an. Sie melden nicht an und tippen kein Skript.
Das Cookie ist wichtig. Ein Skript, das in einer Seite läuft, kann die Cookies der Seite lesen, es sei denn, das Cookie ist als HttpOnly markiert.
Läuft die Website?
curl -s -o /dev/null -w "%{http_code}\n" http://dvwa/login.phpHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Cookies, die die Seite setzt
curl -s -I http://dvwa/login.php | grep -i "^set-cookie"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 Cookies nennen HttpOnly?
curl -s -I http://dvwa/login.php | grep -ic httponlyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Was die drei Ausgaben sagen
Die erste gibt 200 aus. Die zweite gibt zwei Zeilen aus, eine für das Cookie security und eine für PHPSESSID, die Sitzung. Die dritte gibt 0 aus.
Kein Cookie nennt HttpOnly. Ein Skript, das hier in einer Seite liefe, könnte also das Sitzungscookie lesen. Darum führt XSS oft zu gestohlenen Sitzungen.
Escaping macht Sonderzeichen zu Text
Die Lösung ist, den Text eines Besuchers auf dem Weg in eine Seite zu escapen. < wird zu < und > wird zu >. Der Browser zeichnet dieselben Zeichen, liest sie aber nie als Tag.
Ersetzen Sie & zuerst. Tun Sie es zuletzt, wird das & in < zu &, und der Text kommt falsch heraus.
Eine Escape-Funktion
def maskiere(text):
text = text.replace("&", "&")
text = text.replace("<", "<")
text = text.replace(">", ">")
return text
# Ändern Sie die Notiz und führen Sie den Block aus.
# Verschieben Sie danach die &-Zeile ans Ende und führen Sie erneut aus.
notiz = "Tolles Brot <b>und</b> Kuchen & Tee"
print("<p>" + maskiere(notiz) + "</p>")
Ein häufiger Fehler
Warnung
Viele glauben, es genüge, das Wort script beim Speichern einer Notiz zu sperren. Das stimmt nicht. Auch Tags wie img tragen Skript, und Filter übersehen Schreibweisen. Maskieren Sie in dem Moment, in dem Sie Text in eine Seite schreiben, für jeden Wert. Dann stellt sich die Frage nicht mehr.
Bei der Ausgabe maskieren, dazu mehrere Schichten
Maskieren Sie, wenn Sie Text in eine Seite schreiben, nicht beim Speichern. Derselbe Text kann später in eine Seite, eine E-Mail oder eine Datei gehen, und jedes braucht sein eigenes Maskieren.
Fügen Sie Schichten dahinter ein. Markieren Sie Sitzungscookies als HttpOnly. Senden Sie einen Content-Security-Policy-Header, der begrenzt, welche Skripte laufen dürfen. Das begrenzt den Schaden, falls ein Maskieren fehlt.