Sicherheit bei Django-Webanwendungen
Der Schutz von Benutzerdaten ist ein wesentlicher Bestandteil des Webdesigns. In dem Artikel Web-Sicherheit haben wir zuvor einige der häufigsten Sicherheitsbedrohungen erläutert – dieser Artikel bietet eine praktische Demonstration, wie Djangos eingebaute Schutzmaßnahmen diese Bedrohungen abwehren.
Voraussetzungen: | Lesen Sie das Thema zur serverseitigen Programmierung "Website-Sicherheit". Schließen Sie die Django-Tutorial-Themen bis einschließlich Django-Tutorial Teil 9: Arbeiten mit Formularen ab. |
---|---|
Ziel: | Zum Verständnis der Hauptmaßnahmen, die Sie ergreifen müssen (oder nicht ergreifen dürfen), um Ihre Django-Webanwendung abzusichern. |
Übersicht
Das Thema Website-Sicherheit bietet einen Überblick darüber, was Website-Sicherheit für das serverseitige Design bedeutet, und über einige der häufigsten Bedrohungen, gegen die Sie sich schützen sollten. Eine der wichtigsten Botschaften in diesem Artikel ist, dass fast alle Angriffe erfolgreich sind, wenn die Webanwendung Daten vom Browser vertraut.
Warnung:
Die wichtigste Lektion, die Sie über Website-Sicherheit lernen können, ist, niemals Daten vom Browser zu vertrauen. Dies umfasst GET
-Anfragedaten in URL-Parametern, POST
-Daten, HTTP-Header und Cookies, von Benutzern hochgeladene Dateien usw. Überprüfen und bereinigen Sie immer alle eingehenden Daten. Gehen Sie immer vom Schlimmsten aus.
Die gute Nachricht für Django-Nutzer ist, dass viele der häufigsten Bedrohungen vom Framework behandelt werden! Der Artikel Sicherheit in Django (Django-Dokumentation) erklärt Djangos Sicherheitsfunktionen und wie man eine Django-basierte Website absichert.
Häufige Bedrohungen/Schutzmaßnahmen
Anstatt die Django-Dokumentation hier zu wiederholen, demonstrieren wir in diesem Artikel nur einige der Sicherheitsfunktionen im Kontext unseres Django-LocalLibrary-Tutorials.
Cross-Site-Scripting (XSS)
XSS ist ein Begriff für eine Klasse von Angriffen, die es einem Angreifer ermöglichen, clientseitige Skripte über die Website in die Browser anderer Benutzer einzuschleusen. Dies wird üblicherweise erreicht, indem bösartige Skripte in der Datenbank gespeichert werden, wo sie abgerufen und anderen Benutzern angezeigt werden können, oder indem Benutzer dazu gebracht werden, auf einen Link zu klicken, der das JavaScript des Angreifers im Browser des Benutzers ausführt.
Djangos Templatesystem schützt Sie vor den meisten XSS-Angriffen, indem es bestimmte Zeichen entwertet, die in HTML als "gefährlich" gelten. Wir können dies demonstrieren, indem wir versuchen, JavaScript in unsere LocalLibrary-Website über das von uns eingerichtete Autor-Erstellungsformular in Django-Tutorial Teil 9: Arbeiten mit Formularen einzuschleusen.
-
Starten Sie die Website mit dem Entwicklungsserver (
python3 manage.py runserver
). -
Öffnen Sie die Seite in Ihrem lokalen Browser und melden Sie sich mit Ihrem Superuser-Konto an.
-
Navigieren Sie zur Seite zur Autor-Erstellung (die sich unter der URL
http://127.0.0.1:8000/catalog/author/create/
befinden sollte). -
Geben Sie Namen und Datum für einen neuen Benutzer ein und fügen Sie dann den folgenden Text zum Feld Nachname hinzu:
<script>alert('Test alert');</script>
.Hinweis: Dies ist ein harmloses Skript, das, falls ausgeführt, eine Alert-Box in Ihrem Browser anzeigen wird. Wenn die Alert-Box angezeigt wird, wenn Sie den Datensatz absenden, dann ist die Seite anfällig für XSS-Bedrohungen.
-
Drücken Sie Absenden, um den Datensatz zu speichern.
-
Wenn Sie den Autor speichern, wird er wie unten angezeigt. Aufgrund der XSS-Schutzmaßnahmen sollte das
alert()
nicht ausgeführt werden. Stattdessen wird das Skript als Klartext angezeigt.
Wenn Sie den Quellcode der Seite anzeigen, können Sie sehen, dass die gefährlichen Zeichen für die Skript-Tags in ihre harmlosen Escape-Code-Äquivalente umgewandelt wurden (zum Beispiel wurde >
zu >
).
<h1>
Author: Boon<script>alert('Test alert');</script>, David
(Boonie)
</h1>
Der Einsatz von Django-Templates schützt Sie vor den meisten XSS-Angriffen. Es ist jedoch möglich, diesen Schutz zu deaktivieren, und der Schutz wird nicht automatisch auf alle Tags angewandt, die normalerweise nicht mit Benutzereingaben gefüllt würden (zum Beispiel wird der help_text
in einem Formularfeld normalerweise nicht vom Benutzer bereitgestellt, daher entwertet Django diese Werte nicht).
XSS-Angriffe können auch von anderen nicht vertrauenswürdigen Datenquellen, wie Cookies, Webdiensten oder hochgeladenen Dateien, ausgehen (wann immer die Daten nicht ausreichend bereinigt werden, bevor sie in eine Seite eingebunden werden). Wenn Sie Daten aus diesen Quellen anzeigen, müssen Sie möglicherweise Ihren eigenen Bereinigungscode hinzufügen.
Cross-Site-Request-Forgery-(CSRF)-Schutz
CSRF-Angriffe ermöglichen es einem böswilligen Benutzer, Aktionen mit den Anmeldedaten eines anderen Benutzers ohne dessen Wissen oder Zustimmung auszuführen. Betrachten Sie zum Beispiel den Fall, in dem ein Hacker zusätzliche Autoren für unsere LocalLibrary erstellen möchte.
Hinweis: Offensichtlich ist unser Hacker nicht auf das Geld aus! Ein ehrgeizigerer Hacker könnte denselben Ansatz auf anderen Seiten nutzen, um viel schädlichere Aufgaben auszuführen (wie das Überweisen von Geld auf eigene Konten usw.).
Um dies zu erreichen, könnten sie eine HTML-Datei wie die untenstehende erstellen, die ein Autor-Erstellungsformular enthält (wie das, das wir im vorherigen Abschnitt verwendet haben), das sofort beim Laden der Datei übermittelt wird. Sie würden dann die Datei an alle Bibliothekare senden und vorschlagen, dass sie die Datei öffnen (sie enthält einige harmlose Informationen, ehrlich!). Wenn die Datei von einem angemeldeten Bibliothekar geöffnet wird, wird das Formular mit seinen Anmeldedaten übermittelt und ein neuer Autor erstellt.
<html lang="en">
<body onload="document.EvilForm.submit()">
<form
action="http://127.0.0.1:8000/catalog/author/create/"
method="post"
name="EvilForm">
<table>
<tr>
<th><label for="id_first_name">First name:</label></th>
<td>
<input
id="id_first_name"
maxlength="100"
name="first_name"
type="text"
value="Mad"
required />
</td>
</tr>
<tr>
<th><label for="id_last_name">Last name:</label></th>
<td>
<input
id="id_last_name"
maxlength="100"
name="last_name"
type="text"
value="Man"
required />
</td>
</tr>
<tr>
<th><label for="id_date_of_birth">Date of birth:</label></th>
<td>
<input id="id_date_of_birth" name="date_of_birth" type="text" />
</td>
</tr>
<tr>
<th><label for="id_date_of_death">Died:</label></th>
<td>
<input
id="id_date_of_death"
name="date_of_death"
type="text"
value="12/10/2016" />
</td>
</tr>
</table>
<input type="submit" value="Submit" />
</form>
</body>
</html>
Führen Sie den Entwicklungswebserver aus und melden Sie sich mit Ihrem Superuser-Konto an. Kopieren Sie den obigen Text in eine Datei und öffnen Sie diese im Browser. Sie sollten einen CSRF-Fehler erhalten, da Django gegen solche Aktivitäten schützt!
Die Aktivierung des Schutzes erfolgt, indem Sie das Template-Tag {% csrf_token %}
in die Formular-Definition aufnehmen. Dieses Token wird dann wie unten gezeigt in Ihrem HTML mit einem Wert gerendert, der spezifisch für den Benutzer im aktuellen Browser ist.
<input
type="hidden"
name="csrfmiddlewaretoken"
value="0QRWHnYVg776y2l66mcvZqp8alrv4lb8S8lZ4ZJUWGZFA5VHrVfL2mpH29YZ39PW" />
Django generiert einen benutzer-/browser-spezifischen Schlüssel und lehnt Formulare ab, die das Feld nicht enthalten oder einen falschen Feldwert für den Benutzer/Browser enthalten.
Um diesen Angriffstyp zu nutzen, muss der Hacker nun den CSRF-Schlüssel des spezifischen Zielbenutzers entdecken und einfügen. Sie können auch nicht mehr die „Streuerschuss“-Methode verwenden, einer böswilligen Datei an alle Bibliothekare zu senden und darauf zu hoffen, dass einer von ihnen die Datei öffnet, da der CSRF-Schlüssel browserspezifisch ist.
Djangos CSRF-Schutz ist standardmäßig aktiviert. Sie sollten immer das Template-Tag {% csrf_token %}
in Ihren Formularen verwenden und POST
für Anfragen verwenden, die Daten zur Datenbank ändern oder hinzufügen könnten.
Weitere Schutzmaßnahmen
Django bietet auch andere Schutzmechanismen (von denen die meisten schwer oder nicht besonders nützlich zu demonstrieren sind):
- Schutz vor SQL-Injection
-
SQL-Injection-Schwachstellen ermöglichen es böswilligen Benutzern, beliebigen SQL-Code auf einer Datenbank auszuführen, sodass Daten unabhängig von den Benutzerberechtigungen zugegriffen, geändert oder gelöscht werden können. In fast jedem Fall greifen Sie mit Djangos Querysets/Models auf die Datenbank zu, sodass der resultierende SQL-Code vom zugrunde liegenden Datenbanktreiber ordnungsgemäß entwertet wird. Wenn Sie rohe Abfragen oder benutzerdefinierten SQL-Code schreiben müssen, müssen Sie explizit über die Verhinderung von SQL-Injections nachdenken.
- Schutz gegen Clickjacking
-
Bei diesem Angriff nimmt ein böswilliger Benutzer Klicks, die für eine sichtbare Top-Level-Seite gedacht sind, und leitet sie auf eine versteckte Seite darunter. Diese Technik könnte beispielsweise genutzt werden, um eine legitime Bankseite anzuzeigen, aber die Anmeldeinformationen in einem unsichtbaren
<iframe>
zu erfassen, der vom Angreifer kontrolliert wird. Django enthält einen Clickjacking-Schutz in Form desX-Frame-Options
-Middleware, der in einem unterstützenden Browser verhindern kann, dass eine Seite in einem Rahmen gerendert wird. - Durchsetzung von TLS/HTTPS
-
TLS/HTTPS kann auf dem Webserver aktiviert werden, um den gesamten Verkehr zwischen der Seite und dem Browser zu verschlüsseln, einschließlich Anmeldeinformationen, die sonst im Klartext gesendet würden (die Aktivierung von HTTPS wird dringend empfohlen). Wenn HTTPS aktiviert ist, bietet Django mehrere weitere Schutzmaßnahmen, die Sie verwenden können:
SECURE_PROXY_SSL_HEADER
kann verwendet werden, um zu überprüfen, ob der Inhalt sicher ist, selbst wenn er von einem Nicht-HTTP-Proxy stammt.SECURE_SSL_REDIRECT
wird verwendet, um alle HTTP-Anfragen auf HTTPS umzuleiten.- Verwenden Sie HTTP Strict Transport Security (HSTS). Dies ist ein HTTP-Header, der einem Browser mitteilt, dass alle zukünftigen Verbindungen zu einer bestimmten Seite immer HTTPS verwenden sollen. In Kombination mit der Umleitung von HTTP-Anfragen zu HTTPS stellt diese Einstellung sicher, dass HTTPS nach einer erfolgreichen Verbindung immer verwendet wird. HSTS kann entweder mit
SECURE_HSTS_SECONDS
undSECURE_HSTS_INCLUDE_SUBDOMAINS
oder auf dem Webserver konfiguriert werden. - Verwenden Sie 'sichere' Cookies, indem Sie
SESSION_COOKIE_SECURE
undCSRF_COOKIE_SECURE
aufTrue
setzen. Dies stellt sicher, dass Cookies nur über HTTPS gesendet werden.
- Validierung des Host-Headers
-
Verwenden Sie
ALLOWED_HOSTS
, um nur Anfragen von vertrauenswürdigen Hosts zu akzeptieren.
Es gibt viele weitere Schutzmaßnahmen und Hinweise zur Nutzung der oben genannten Mechanismen. Wir hoffen, dass dies Ihnen einen Überblick darüber gibt, was Django bietet, aber Sie sollten trotzdem die Django-Sicherheitsdokumentation lesen.
Zusammenfassung
Django bietet effektive Schutzmaßnahmen gegen eine Reihe von häufigen Bedrohungen, einschließlich XSS- und CSRF-Angriffen. In diesem Artikel haben wir demonstriert, wie diese spezifischen Bedrohungen von Django auf unserer LocalLibrary-Website behandelt werden. Wir haben auch einen kurzen Überblick über einige der anderen Schutzmaßnahmen gegeben.
Dies war nur ein sehr kurzer Ausflug in die Web-Sicherheit. Wir empfehlen dringend, Sicherheit in Django zu lesen, um ein tieferes Verständnis zu gewinnen.
Der nächste und letzte Schritt in diesem Modul über Django ist die abschließende Bearbeitung der Bewertungsaufgabe.
Siehe auch
- Sicherheit im Web
- Praktische Leitfäden zur Umsetzung von Sicherheitsmaßnahmen
- Sicherheit in Django (Django-Dokumentation)