Das Problem mit den Symlinks und Apache
Vor kurzem sind wir durch einen Blog-Post eines Administrators von Uberspace auf ein Problem aufmerksam geworden, das auch unsere Kunden betraf.
Der Apache-Webserver besitzt eine Option FollowSymlinks, die üblicherweise aktiviert ist. Der Name ist eigentlich selbsterklärend: Die Option führt dazu, dass der Webserver beim Dateiabruf Symlinks folgt.
Nun gibt es folgendes Problem: Zwar gehören alle Dateien einer Webanwendung dem jeweiligen User, aber damit der Webserver darauf zugreifen kann, müssen die entsprechenden Dateien Lesezugriff für den Webserver erlauben. Wir lösen das bei uns üblicherweise damit, dass das websites-Verzeichnis eine Default-ACL besitzt, die den Lesezugriff für den Webserver regelt.
Das Problem: Ein Nutzer kann nun einen Symlink erstellen, der auf die Datei eines anderen Nutzers verweist. Zwar kann er selbst nicht auf diesen Symlink zugreifen, da das die Rechteverwaltung von Linux verhindert, aber der Webserver kann die Datei lesen. Damit kann der Nutzer die Datei über's Web abrufen. Damit könnte ein Nutzer beispielsweise die Wordpress-Konfiguration eines anderen Nutzers samt Datenbankpasswort lesen. Ein gravierendes Sicherheitsproblem.
Um genau dieses Problem zu vermeiden besitzt Apache neben FollowSymlinks auch eine Option SymLinksIfOwnerMatch. Diese Option folgt Symlinks nur dann, wenn die verlinkte Datei dem selben Nutzer gehört. Das würde also theoretisch unser Problem lösen: FollowSymlinks ausschalten, SymLinksIfOwnerMatch anschalten und fertig.
Leider ist es nicht so einfach. Denn viele Webanwendungen setzen selbst die Option FollowSymlinks über die .htaccess-Datei. Das Problem: Verbieten wir diese Option dann funktionieren diese Webanwendungen schlicht nicht mehr, alle Anfragen werden beim Versuch, eine nicht erlaubte Option mittels .htaccess-Datei zu setzen, mit einem Error 500 beantwortet. Das würde beispielsweise bedeuten, dass man ein gängiges CMS-Systeme wie Drupal nicht mehr installieren könnte, ohne manuell an den Konfigurationsdateien Änderungen vorzunehmen. Bei Drupal gibt es dazu einen Bugreport, allerdings ist dieser dort schon vier Jahre offen, eine schnelle Lösung ist also von dort nicht zu erwarten. Vermutlich gibt es eine ganze Reihe weiterer Anwendungen, die das selbe Problem haben.
Dazu kommt: Apache schreibt selbst, dass die Option SymLinksIfOwnerMatch nicht sicher ist. Sie ist durch eine Race-Condition verwundbar und mit etwas Aufwand kann ein Anwender möglicherweise trotzdem Dateien anderer Nutzer auslesen.
Wir haben also eine gravierende Sicherheitslücke und Apache bietet nur eine Lösung, die nicht wirklich funktioniert und außerdem dazu führt, dass viele gängige Webanwendungen nicht mehr funktionieren. Keine besonders erfreuliche Situation. Als mögliche Abhilfe hatten wir diskutiert, Apache zu patchen, so dass die entsprechende Option umbenannt oder ignoriert wird, oder regelmäßig durch ein Skript alle .htaccess-Dateien zu durchstöbern. Das Problem mit der Race-Kondition würden wir damit allerdings auch nicht lösen.
Nach einigen Recherchen sind wir jedoch auf eine Lösung gestoßen: Der Grsecurity-Patch für den Linux bietet eine im Kernel implementierte Funktion an, die den Zugriff auf Symlinks einschränken kann. Das ist soweit wir das bisher recherchiert haben die einzige Lösung, die wirklich sicher ist und nicht zu schwierigen Komplikationen führt. Wir haben die entsprechende Option aktiviert und alle Kundenserver neu gestartet.
Grsecurity nutzen wir schon lange, die Aktivierung der entsprechenden Option war somit keine große Änderung. Der Einsatz von Grsecurity hat sich für uns über lange Zeit bewährt. Wenn Sicherheitslücken im Linux-Kernel bekannt werden ist es fast immer so, dass die Ausnutzung durch Grsecurity erschwert oder unmöglich gemacht wird. Wir können nur jedem, der sicherheitskritische Systeme betreibt, die Nutzung von Grsecurity nahelegen. Da wir sehr froh sind, dass es dieses Projekt gibt, haben wir beschlossen, den Entwicklern eine kleine finanzielle Spende zukommen zu lassen.
Überraschend war für uns, dass Apache selbst keine wirklich brauchbare Lösung für dieses Problem bereitstellt. Wir gehen davon aus, dass sehr viele Webhoster von diesem Problem betroffen sind. Wer Grsecurity nicht nutzen kann oder möchte oder wer ein BSD-System einsetzt dem steht die von uns verwendete Lösung nicht zur Verfügung.
Update: Die Patches von Grsecurity sind inzwischen nicht mehr öffentlich verfügbar. Wir pflegen daher das Feature zur Absicherung von Symlinks selbst in einem Patch, den wir auch hier bereitstellen.