Lighttpd, Rewrite und ein merkwürdiger Error-handler

frank
Goto Top
Aus dem Alltag eine Admins: Eigentlich wollte ich etwas ganz anders machen, doch als ich eine Mail mit einer Update-Aufforderung für Matomo bekam, änderte sich mein Tag. Das Update lief wie immer sauber durch, doch am Ende gab es eine Fehlermeldung über öffentliche Zugriffe auf das /config/ und /tmp/ Verzeichnis. Hä?

back-to-topProblem access-deny?


Natürlich sind die Verzeichnisse in der Konfiguration des Webservers per "access-deny" gesperrt, also warum werden sie mir als lesbar angezeigt? Als Erstes prüfte ich die Konfiguration (Webserver, PHP, etc.), die war in Ordnung, dann testete ich den Zugriff auf die Verzeichnisse und ja, verdammt, es sieht so aus, als wären sie wirklich von außen erreichbar. Prinzipiell nicht schlimm, da es PHP-Dateien sind, die keine Inhalte anzeigen. Was geschieht aber, wenn der PHP-Praser mal nicht funktioniert, immerhin steht hier die Konfiguration von Matomo drin!

Dann kam ich auf die Idee, die Versionen des Webservers zu vergleichen. Als Webserver läuft bei uns ein Lighttpd und das schon seit über 20 Jahren. Das ist ein kleiner, feiner und sehr schneller Webserver, der perfekt mit FPM-PHP umgehen kann. Er ist dem "nginx" sehr ähnlich, aber älter. Durch den Wechsel von Ubuntu 20.04 auf 22.04 LTS hatten wir einen großen Versionssprung.

Hier die unterschiedlichen Versionen in Ubuntu: Lighttpd Version 1.4.55, Ubuntu 20.04 LTS vs Lighttpd Version 1.4.63, Ubuntu 22.04 LTS.

In der Konfiguration sperrt man komplette Verzeichnisse (und die Dateien dahinter) mit folgendem Code:


Es sah so aus, als würde das nur dann richtig funktionieren, wenn kein globaler Rewrite in der Konfiguration steht. Matomo hat einen globalen Rewrite für alle Dateien hin zur "index.php" Datei in seiner Konfiguration stehen. In der Lighttpd Konfiguration sieht das dann so aus:


Ist der Rewrite eingerichtet, scheint der Webserver das "url.access-deny" zu ignorieren. Das führt dazu, das der eigentliche geschützte Pfad /config/ mit dem Inhalt der Rewrite-Datei "index.php" angezeigt wird. Das wiederum verwirrt die Prüfscripte von Matomo, da sie eigentlich den HTTP-Code 403 erwarten, statt dessen aber einen HTTP-Code 200 OK als Antwort bekommen. Nehme ich den globalen Rewrite raus, funktioniert es wie gehabt: Es erscheint die typische 403 Meldung und alles ist in Ordnung. Aktiviere ich den globalen Rewrite erneut, wird das Verzeichnis /config/ mit dem Inhalt der globalen Weiterleitung "index.php" angezeigt.

Eine Sicherheitslücke ist das nicht. Es sieht von außen nur so aus, als hätte man Zugriff auf die geschützten Verzeichnisse, in Wahrheit wir nur der Inhalt der Weiterleitungs-Datei "index.php" angezeigt. Ist keine "index.php" vorhanden, besteht weiterhin der Schutz durch "url.access-deny".

Hätte die Matomo Systemprüfung nicht mit großen roten Hinweisen gemeckert, wäre mir dieses Verhalten gar nicht aufgefallen.

back-to-topFehler gefunden


Nach einigen Test und intensiver Diskussion mit einem Lighttpd Entwickler finde ich den Grund für den Fehler: In der Konfiguration für die 404-Seite. Dort gibt es die Einstellung "error-handler-404":


Ist der "error-handler-404" gesetzt, reagiert dieser auch auf alle 403 Fehler (laut lighttpd Entwickler eine historische Entscheidung) und die Datei "404.php" wird aufgerufen. Die angegebene Datei "404.php" existiert bei uns nicht mehr und so kommt die "rewrite-if-not-file" Regel ins Spiel, die einen Rewrite auf die globale "index.php" macht. Das wiederum führt dazu das der HTTP-Status 200-OK ausgegeben wird und nicht der erwartete HTTP-Status 403 Forbidden. Aber selbst wenn die "404.php"-Datei existieren würde, würde anstelle des 403 ein 200er Status erscheinen, es sei denn man baut in die Fehlerseite noch per HEADER einen Fehler-Status ein.

back-to-topLösung(en)


Einfach die veraltete Konfiguration "server.error-handler-404" entfernen bzw. durch den besseren "server.errorfile-prefix" ersetzen (siehe dazu die Lighttpd-Dokumentation).

Eine weitere Lösung mit "mod_magnet" findet ihr im Ticket mit dem Entwickler.

Unsere Lösung bevorzugt den Weg über den HAProxy. Dieser steht vor dem Webserver und übernimmt stattdessen die Absicherung der Verzeichnisse. Dort kann man, wie wahrscheinlich bei jedem Web-Proxy, eigene "deny" Regeln für Verzeichnisse und Domänen setzten. Mit den ACLs (ab Version 1.8) wurde das vereinfacht.

Hier unsere HAProxy Konfiguration (nur der wichtigste Teil davon). Die Regel gilt nur für die Domäne xyz-beispiel.de und bezieht sich auf Matomo:


Wenn man will, kann man das auch noch global mit bestimmten Endungen erweitern. Dann muss der Webserver das nicht mehr machen (ist effizienter, wenn es der HAProxy macht). Folgendes ist nur ein Ausschnitt an Endungen:


Ich hoffe, mein Betrag kann einem verzweifelten Admin, der eine ähnliche Konfiguration besitzt, helfen. Mich hat es ungefähr 8 Stunden gekostet (erkennen, prüfen, fixen, testen, ausliefern).

Gruß
Frank

Content-Key: 3544490449

Url: https://administrator.de/contentid/3544490449

Ausgedruckt am: 19.08.2022 um 00:08 Uhr

Mitglied: 0xFFFF
0xFFFF 04.08.2022, aktualisiert am 05.08.2022 um 12:46:49 Uhr
Goto Top
Hallo Frank,

danke für Deinen Beitrag, werde ich in meiner Umgebung gegenprüfen.

Gekühlte Grüße
Mitglied: Frank
Frank 05.08.2022, aktualisiert am 07.08.2022 um 00:28:03 Uhr
Goto Top
Ich habe ein Ticket bei Lighttpd dazu angelegt: https://redmine.lighttpd.net/issues/3167

Gruß
Frank
Mitglied: Frank
Frank 06.08.2022, aktualisiert am 07.08.2022 um 00:30:14 Uhr
Goto Top
Update nach einigen neuen Tests:

Hat man wie oben beschrieben einen globalen Rewrite drin, führt das dazu, dass der eigentliche geschützte Pfad "/config/" mit dem Inhalt der Rewrite Datei "index.php" angezeigt wird.

Das wiederum verwirrt die Prüfscripte von Matomo, da sie eigentlich den "HTTP-Code 403" erwarten, sie statt dessen aber einen "HTTP-Code 200 OK" als Antwort bekommen.

Eine Sicherheitslücke ist das nicht. Es sieht von außen nur so aus, als hätte man Zugriff auf die geschützten Verzeichnisse, in Wahrheit wir aber nur der Inhalt der Weiterleitungs-Datei "index.php" angezeigt. Sobald die "index.php" nicht vorhanden ist, oder sie nicht richtig ausgeliefert wird, bestehen der Schutz durch "url.access-deny" weiterhin.

So wie es aussieht liegt der Fehler an einer Einstellung des "error-handler-404".

Ich habe den Text oben angepasst.

Gruß
Frank