Blog Passwortgeschützte Seiten und Referrer-Policies

Passwortgeschützte Seiten und Referrer-Policies

WordPress hat eine einfache Methode, einzelne Seiten mit einem Passwort zu schützen. Dabei handelt es sich nicht um einen echten Login (mit unterschiedlichen Login-Daten für diverse Benutzer des Systems), sondern um ein einfaches Passwort (eines für alle), dass den Zugriff auf die Seite vor unbefugten Blicken schützt.

Immer wieder gerne wird dabei übrigens übersehen, dass die auf dieser passwortgeschützten Seite eingefügten Medien-Inhalte (Bilder, PDF-Dokumente, o.ä.) nicht passwortgeschützt sind. Ist der Direktlink zu diesen Medien bekannt, können diese ohne Passworteingabe aufgerufen werden. Aber ich schweife ab…

Ich verwende den Passwortmechanismus von WordPress eher selten, weil die Anforderungen an die Funktionalität meist höher sind (verschiedene Benutzer mit eigenem Login, individuelle Rechtevergabe, Schutz auch der eingebetteten Mediendaten etc.), jedoch hatte ich vor Kurzem noch mal einen Anwendungsfall auf einer eigenen Website. Beim Testen der Funktionalität fiel mir auf, dass mir nach Eingabe des Passworts nicht die eigentliche Seite angezeigt wurde, sondern ich eine leere, weiße Seite erhielt mit der URL

wp-login.php?action=postpass.

Als ich die passwortgeschützte Seite erneut manuell aufrief, wurde mir der Inhalt dann aber korrekt angezeigt, die Passworteingabe selbst wurde anscheinend also erfolgreich registriert.

Was genau passiert beim WordPress-Passwortschutz?

Nach Eingabe des Passworts wird ein Formular abgesendet, als Form-Action ist die oben genannte WP-Login-URL hinterlegt. Das Passwort wird geprüft und bei korrekter Eingabe findet ein Redirect auf die (nun freigeschaltete) Inhaltsseite statt. In meinem Fall fehlte der Redirect als zweiter Schritt offensichtlich, wobei der erste Teil erfolgreich durchgeführt wurde. Damit statt dem Passwort-Formular der eigentliche Seiteninhalt angezeigt wird, wird wordpress-seitig noch ein entsprechendes Cookie gesetzt. Meine Überprüfung ergab, dass auch dieses Cookie korrekt gesetzt wurde.

Nach ein wenig Recherche konnte ich feststellen, dass der Redirect auf die Inhaltsseite fehlschlug, weil WordPress nicht bekannt war, zu welcher Seite weitergeleitet werden sollte. Nach der Passworteingabe ermittelt WordPress die ursprüngliche Seite aus dem Referrer-Header, den der Browser / Webserver mitsendet. Offensichtlich fehlte dieser hier.

Was ist ein Referrer-Header und warum fehlte dieser bei mir?

Der Referrer gibt an, von welcher URL eine Anfrage ausgelöst wurde, man kann so also feststellen, welche Seite vor der gerade aufgerufenen Seite betrachtet wurde. Auch in der Besucherstatistik wird dies gerne genutzt, um zu ermitteln, woher die Besucher kamen und welchen Links und Angeboten sie gefolgt sind.

Üblicherweise wird dieser Header im HTTP-Request übergeben und kann serverseitig ausgelesen werden. WordPress nutzt dies, um zu erfahren, von welcher Seite der Aufruf kam und sendet nach erfolgreicher Authentifizierung den Besucher wieder dahin zurück.

Nun ist es möglich, bei der Konfiguration des Webservers einzustellen, wie mit Referrer-Informationen umgegangen werden soll. Denn grundsätzlich können mitgesendete Referrer-URLs sensitive Informationen enthalten, von denen unter Umständen nicht gewünscht ist, dass diese übertragen werden. Dies könnten zum Beispiel personenbezogene Daten wie Kundennummern o.ä. aus URLs sein (man ist eingeloggt in einer Web-Applikation, die dynamische URLs dieser Art aufbaut und ruft danach eine andere Website auf). Insbesondere in DSGVO-Zeiten höre ich immer häufiger, dass das Mitsenden eines Referrers nicht empfohlen ist – ob das wirklich relevant ist, sei mal dahin gestellt.

Und damit haben wir aber auch schon die Lösung. Im Rahmen der Absicherung meiner Website und der Überprüfung mit Siwecos hatte ich den HTTP-Header Referrer-Policy auf „no-referrer“ gestellt. Dies führt dazu, dass keinerlei Referrer-Header mitgeliefert werden und somit WordPress keine Ahnung hatte, wohin ich nach erfolgreicher Passwortprüfung weitergeleitet werden sollte.

Die Lösung (sollte ich eher sagen „Workaround“?) an dieser Stelle war dann, den Referrer-Policy-Header auf „strict-origin-when-cross-origin“ zu stellen. Dies führt dazu, dass Referrer bei Requests auf derselben Domain noch mitgeliefert werden und nur für Requests von externen Quellen unterdrückt werden. Für die Passworteingabe wird also weiterhin ein Referrer-Header mitgeliefert, da der Request auf derselben Domain stattfindet.

Die Anpassung des Security-Headers habe ich in meiner .htaccess-Datei vorgenommen (Apache-Webserver) und sah folgendermaßen aus:

Header set Referrer-Policy „strict-origin-when-cross-origin“

Natürlich kann man diese Header grundsätzlich auch bei einer nginx-Konfiguration setzen.

Und siehe da: plötzlich funktionierte der Passwortschutz wieder. 😉

Der Referrer-Policy-Header (Details) gehört zu den neueren HTTP-Security-Headern. Einen Überblick gibt es zum Beispiel bei OWASP.

Workaround oder nicht? Gibt es eine optimalere Lösung?

Ich habe mich dann auf die Suche gemacht und entdeckt, dass ich nicht alleine mit diesem Problem bin. Auch andere haben das Problem und entsprechende Trac-Tickets eröffnet (44991, 23412, 16482, 49136). Teilweise sind die Tickets schon einige Jahre alt, behandeln deswegen aber „nur“ ähnliche Probleme, da der Referrer-Policy-Header erst 2017 eingeführt wurde. Eine konkrete Lösung wurde in den Tickets bislang nicht präsentiert.

Sollte man überhaupt bei der Lösung des Problems auf den Referrer-Header setzen? Ersatzweise könnte man in das Passwort-Formular auch ein verstecktes Feld einbinden, welches die Redirect-URL enthält. Äh, nein. Das wäre zu einfach. Zu einfach zu manipulieren. Würde ohne Prüfung auf die dort eingegebene URL weitergeleitet, könnte diese vor Absenden des Formulars per JavaScript manipuliert werden und dazu führen, dass eine ganz andere Seite (die ggf. auch passwortgeschützt war) plötzlich aufgerufen würde.

Einschub: ganz so einfach ist es natürlich nicht, da für verschiedene Seiten einer Website mit unterschiedlichen Passwörtern unterschiedliche Postpass-Cookies angelegt werden, so dass die Legitimation hier schon grundsätzlich unterschieden werden kann. Haben mehrere Seiten das gleiche hinterlegte Passwort, reicht jedoch die einmalige Eingabe des Passworts, um auf alle so geschützten Seiten Zugriff zu haben. In diesem Fall wäre dem Besucher der Zugriff aber ja sowieso nicht generell verwehrt worden.
Relevant könnte eine solche Manipulation aber im Falle eines Angriffs sein, der den Besucher dann z.B. auf eine Phishing-Seite anstatt der eigentlich erwarteten Seite weiterleitet. Dazu müsste ein Angreifer die Möglichkeit haben, in die Website JavaScript einzuschmuggeln, um damit dann das Passwort-Formular zu manipulieren.

Die sicherste Lösung wäre also vermutlich hier ein Token / Nonce als Teil des Formulars. Dieser Token wird serverseitig beim Laden der Seite erzeugt und in der Datenbank zusammen mit der aufgerufenen URL hinterlegt. Wird das Passwort korrekt eingegeben, kann der Token auf Gültigkeit überprüft werden (z.B. Ablauf der Gültigkeit nach einer gewissen Zeitspanne) und der Redirect findet auf die am Token in der Datenbank hinterlegte URL statt. Zugegeben: eine ziemliche große Lösung für ein sehr spezielles Problem.

Bleibt also die Frage: ist die Umsetzung des Passwortschutzes basierend auf dem Referrer-Header noch zeitgemäß? Oder sollte eine andere Lösung implementiert werden? Und wenn ja, welche? 😉

Warum dieses Beitragsbild? Es geht doch um Sicherheit und Header, da ist doch klar, dass es ein Bild sein muss mit „Sicherheit“ und „Kopf“ 😉

2 Gedanken zu „Passwortgeschützte Seiten und Referrer-Policies“

  1. Denke eine Kombination aus deineer verworfenen und vorgeschlagenen lösung wäre einfacher und mit Boardmitteln sofort machbar.

    Das versteckte Feld mit der Post-ID und einen Nonce in das Formular einbinden. Dann kann vor dem Redirect geschaut werden ob der Post ein Password braucht und über den Nonce zusätzlich verifiziert werden ob das Formular valide ist.

    Antworten

Schreibe einen Kommentar