FollowSymLinks vs. SymLinksIfOwnerMatch

Wir haben bei Uberspace.de Mist gebaut – da gibt es wenig zu beschönigen. Unsere Konfiguration des Apache-Webservers hatte – immer schon – die Option FollowSymLinks standardmäßig aktiviert, damit der Apache, nun ja: Symlinks folgt. Das ist wichtig, weil Symlinks weit verbreitet sind und nicht zuletzt auch die Verzeichnisstrukturen vieler Webapplikationen intensiv auf Symlinks setzen.

tl;dr

  • Unsere Apache-Konfiguration wies eine Konfigurationsschwäche auf, die es über Symlink-Attacken lokalen Usern ermöglichte, Dateien außerhalb des eigenen DocumentRoots einzusehen, sofern jene für den Apache lesbar waren.
  • Das Problem betraf explizit nicht den Inhalt von Home-Verzeichnissen anderer User und auch nicht deren Datenbanken – aber die Inhalte in den DocumentRoots anderer User, sofern die darin abgelegten Dateien world-readable waren.
  • Ebenfalls betroffen war die /etc/shadow, die in unserem Setup zwar nicht für normale User, aber für den Apache-Webserver lesbar und damit auch durch die Symlink-Attacke angreifbar war.
  • Das Problem ist durch eine Policy-Änderung gefixt, die künftig statt Options +FollowSymLinks nur noch Options +SymLinksIfOwnerMatch erlaubt.
  • Wir mussten dazu .htaccess-Dateien von Usern, die Options +FollowSymLinks einsetzen, automatisiert anpassen, damit jene weiterhin funktionieren.

Das würde ich gerne im Detail verstehen.

Symlinks sind vom Rechteaspekt her erstmal kein Problem: Es gelten immer die Berechtigungen des Symlink-Ziels. Setze ich einen Symlink auf eine Datei, die ich nicht lesen darf, und greife dann auf den Symlink zu, kann ich – natürlich – auch weiterhin nicht die Datei lesen, die ich nicht lesen darf. Deshalb stellen Symlinks auch kein Sicherheitsproblem per se dar; spätestens auf der Shell gäbe es auch gar keine Möglichkeit (und auch keinen Anlass), jene zu verhindern.

Im Kontext des Apache-Webservers stellt sich die Situation allerdings etwas anders dar, was wir nicht ausreichend bedacht haben und worauf wir von einem aufmerksamen User hingewiesen wurden. Denn: Auf der Shell habe ich die Berechtigungen des Users, mit dessen Zugangsdaten ich gerade eingeloggt bin, also beispielsweise des User jonas. Dynamische Inhalte innerhalb des Webservers werden durch suEXEC ebenfalls mit den Rechten des jeweiligen Users, also beispielsweise des Users jonas, ausgeführt. Sie können damit also genau das lesen bzw. nicht lesen, was ich auch auf der Shell lesen bzw. nicht lesen kann.

Für die Auslieferung statischer Dateien hingegen gibt es keinen Kontextwechsel vom User apache zu jeweiligen User-ID wie z.B. jonas, das heißt, Dateien die in /var/www/virtual/$USER liegen, müssen world-readable sein, wenn der Apache sie direkt selbst ausliefern können soll, denn die Dateien gehören schließlich alle dem User und der Gruppe dessen, der sie hochgeladen hat – wären sie nicht world-readable, könnte der Apache sie nicht ausliefern. Dass andere User jene Dateien nicht einsehen können, wird dadurch geregelt, dass das Verzeichnis /var/www/virtual/$USER nur für den Eigentümer sowie für den Apache lesbar sind, aber eben nicht für andere User. Jene könnten insofern zwar von den Rechten der Zieldateien her jene lesen, aber da jene in einem Verzeichnis liegen, das ein Weiterkommen verhindert, wird das effektiv verhindert. Das funktioniert auch einwandfrei. (Wir stellen übrigens auch sicher, dass dann, wenn User das Verzeichnis /var/www/virtual/$USER eigenständig world-readable machen und damit die Barriere selbstständig einreißen, jene Berechtigungen automatisch wieder auf den sicheren Default zurückgesetzt werden und der betreffende User informiert wird.)

Und nun kommen die Symlinks ins Spiel. Wir hatten ja eben bereits klargestellt, dass der Symlink rechtemäßig nichts daran ändert, ob ein User auf eine Datei zugreifen kann oder nicht. Nun ist es in diesem Fall aber ja kein normaler Systemuser wie eben beispielsweise jonas, der dem Symlink zu folgen und die Zieldatei zu lesen hat, sondern es ist der User apache, dem es gestattet ist (und sein muss), die für User unzugängliche Barriere /var/www/virtual/$USER zu übergehen.

Das bedeutet im Klartext: Legt ein User A einen Symlink auf eine Datei von User B an, so kann er selbst davon zwar die Datei noch nicht lesen – legt er den Symlink aber innerhalb seines DocumentRoots an und ruft die entsprechende URL auf, die zu diesem Symlink führt, veranlasst er damit den User apache, dem Symlink zu folgen – und der darf das. Damit kann sich ein User indirekt Zugriff auf die Dateien anderer User verschaffen, sofern jene für den Apache lesbar sind, auch wenn der User die Datei selbst nicht lesen darf. Voraussetzung ist aber eben, dass er den Pfad zur Zieldatei kennen muss, denn er muss ja den Symlink erstmal konstruieren.

Das ist schlimm, keine Frage. Dateien anderer User enthalten potentiell sensible und/oder persönliche Daten, die nicht in falsche Hände geraten sollten. Ein zusätzlicher Schmerzpunkt ist, dass auch ein .htaccess-basierter Verzeichnisschutz hier mit diesem Angriffsvektor umgangen werden kann. Das macht diesen Angriff klar zu einem Fehler der Kategorie „OMFG, das hätte uns niemals passieren dürfen“. Es ist aber passiert.

Warum ist das zwar schlimm, aber vielleicht nicht so schlimm?

Es gibt eine Reihe von Aspekten, die eine möglich Panik auf der anderen Seite auch wieder entschärfen können.

  • Alles, was im Home-Verzeichnis /home/$USER liegt, ist nicht betroffen, denn dort hat der Apache bewusst keinerlei Zugriff. Das betrifft insbesondere Konfigurationsdateien wie die .my.cnf, die dein MySQL-Passwort enthält, deine Mailkonfiguration und dein Mailbestand, sowie die Daten selbst installierter Dienste wie z.B. einer MongoDB oder einer PostgreSQL-Instanz.
  • Auch deine MySQL-Datenbanken sind davon nicht betroffen, da der Apache auf jene prinzipiell keinen Zugriff hat.
  • Eine von den Berechtigungen her sensibel konfigurierte webbasierte Applikation ist ebenfalls nicht betroffen. Um’s an einem Beispiel deutlich zu machen: Nehmen wir eine hypothetische index.php mit Programmcode, die eine config.php per include() einbindet, die dann sensible Daten wie z.B. MySQL-Zugangsdaten beinhaltet – dann müsste lediglich die index.php für den Apache lesbar sein, die config.php jedoch nicht, denn diese wird nicht vom Apache gelesen, sondern vom PHP-Interpreter, der unter der ID des betreffenden Users läuft. Sie müsste insofern nicht world-readable sein und wäre dann auch nicht für die Symlink-Attacke anfällig gewesen. Einige Webapplikationen sind auch tatsächlich out-of-the-box so sensibel konfiguriert, aber machen wir uns nichts vor: Die Mehrheit der Applikationen ist das nicht. Wir weisen in unserem Wiki aber auch wiederholt darauf hin, dass eigenständig laufende Applikationen (also z.B. node.js-Dienste) ohnehin nichts im DocumentRoot zu suchen haben.
  • Es handelt sich nicht um ein Problem, das von beliebigen Dritten aus der Ferne ausgenutzt werden könnte. Das Setzen von Symlinks setzt einen lokalen Useraccount auf der jeweiligen Maschine voraus. Damit ist zum einen die Zahl der hypothetisch möglichen Angreifer sehr gering; zum anderen können Angreifer auch nicht gezielt auf einem System, auf dem sich ein bestimmtes „Opfer“ befindet, einen Account anlegen, denn neue Accounts werden immer nur auf die jeweils neuesten 2-3 Hosts verteilt; alle anderen sind für neue Accounts gesperrt.
  • Es ist die Kenntnis des konkreten Pfads und Dateinamens nötig, um einen Symlink dorthin konstruieren zu können. Ein Angreifer bräuchte also in jedem Fall schon gewisses Vorwissen über den Zielaccount.

Die /etc/shadow – ein Sonderfall

Einen Sonderfall nimmt die /etc/shadow ein – die Userdatenbank, die die Passwort-Hashes beinhaltet und die für User normalerweise auch nicht lesbar ist. Sie ist allerdings für den Apache lesbar, weil die Authentifizierung für den Zugriff auf die Webalizer-Statistiken darüber läuft, und damit ist sie ganz genauso für die Symlink-Attacke anfällig. Es war damit lokalen Usern auf dem System möglich, einen Symlink zu konstruieren, über den sie den Inhalt der /etc/shadow auslesen konnten. Auch hier gibt es jedoch einige Aspekte, die dies relativieren:

  • Nicht wenige User verwenden überhaupt kein SSH-Passwort, sondern loggen sich via SSH-Keys ein (was wir ohnehin empfehlen). In diesem Fall enthält die /etc/shadow keinerlei relevante Informationen.
  • Wir haben bewusst den Standard-Hashing-Algorithmus der eingesetzten Linux-Distribution explizit auf SHA-512 konfiguriert und damit auf den stärksten möglichen Hashing-Algorithmus, den die Distribution unterstützt. Der Einsatz eines Salt verhindert, dass fertige Tabellen aus „beliebten Passwörtern“ und ihren Hashwerten zum Einsatz kommen könnten, mit deren Hilfe man anhand eines Hashwerts das zugrundeligende Passwort einfach nachschlagen könnte.
  • Wir forcieren starke Passwörter, die sich wahlweise durch Länge oder durch die Verwendung unterschiedlicher Zeichenklassen auszeichnen und insofern potentiell nur ziemlich schwer durch Brute-Force-Attacken angegangen werden können.

Alles in allem ist eine Herbeiführung absichtlicher Hashkollisionen (grob vereinfacht ausgedrückt, das „Erraten des Passworts“) damit als sehr, sehr schwer anzusehen. Angesichts dessen, dass die Datei eben auch nicht in die Hände völlig unbekannter Dritter geraten ist, sondern maximal von lokalen Usern über Umwege eingesehen werden konnte, sehen wir hier nur einen minimalen Angriffsvektor. Dass eine regelmäßige Passwortänderung völlig unabhängig von einem konkreten Vorfall immer eine gute Idee ist, sollte mittlerweile wirklich zum Allgemeinwissen gehören.

Der Grund, dass seit Bekanntwerden der Möglichkeit der Symlink-Attacke die Webalizer-Statistiken nicht abrufbar waren, hängt genau damit zusammen; wir hatten hier die /etc/shadow bis zum endgültigen Fix zunächst nur noch für root lesbar gemacht, um zumindest diesen – via Twitter öffentlich bekannt gewordenen – Angriffsvektor ad hoc zu beseitigen.

Was haben wir nun letztlich geändert?

Die Lösung ist so trivial, dass wir uns wirklich doppelt und dreifach ärgern, das nicht gleich richtig gemacht zu haben (und uns ein kleines bisschen auch fragen, warum nicht von Haus aus die sicherere Variante der Default im Apache ist): Der Apache stellt mit SymLinksIfOwnerMatch eine Option bereit, die im Wesentlich exakt das gleiche tut wie FollowSymLinks, aber gleichzeitig überprüft, ob das Symlinkziel dem gleichen User gehört wie der Symlink selbst. Damit folgt der Apache Symlinks auf Dateien anderer User oder auf Dateien wie die /etc/shadow schlicht nicht mehr, und der Angriffsvektor ist weg. Das war’s auch schon, und das haben wir nun so umgestellt. Problem gelöst. Konkret haben wir die Einstellung

AllowOverride All

… wie folgt geändert:

AllowOverride AuthConfig FileInfo Indexes Limit Options=ExecCGI,Includes,Indexes,SymLinksIfOwnerMatch

Das entspricht einem All abzüglich der Option FollowSymLinks (es gibt nur keine elegante Möglichkeit, um „alles, außer …“ auszudrücken).

Das hat aber auch zur Folge, dass überall dort, wo User Options +FollowSymLinks in einer .htaccess-Datei hatten, eingegriffen werden musste. Bisher war diese Option schlicht redundant, weil Options +FollowSymLinks ja schon unsererseits global aktiviert war (das heißt, es war ohnehin unnötig, sie anzugeben, aber machte eben auch keine Probleme). Ab sofort ist aber nun eben nur noch Options +SymLinksIfOwnerMatch zulässig, und das heißt, dass ein und dieselbe .htaccess-Datei, die bisher einwandfrei funktioniert hat, künftig einen Internal Server Error werfen würde – obwohl die benötigte Funktionalität sich mit Options +SymLinksIfOwnerMatch problemlos abdecken ließe; es muss nur eben entsprechend geändert werden. Prominentes Beispiel dafür wäre unter anderem das Joomla!-CMS, das in seiner Default-.htaccess-Datei diesen Abschnitt vorgibt (insbesondere die Kommentarzeilen sind hier interessant):

# The line just below this section: 'Options +FollowSymLinks' may cause problems
# with some server configurations.  It is required for use of mod_rewrite, but may already
# be set by your server administrator in a way that dissallows changing it in
# your .htaccess file.  If using it causes your server to error out, comment it out (add # to
# beginning of line), reload your site in your browser and test your sef url's.  If they work,
# it has been set by your server administrator and you do not need it set here.
##

## Can be commented out if causes errors, see notes above.
Options +FollowSymLinks

Zwischen den Zeilen gelesen muss man wohl zu dem Schluss kommen, dass auch die Joomla!-Entwickler nicht wirklich vertraut mit der Existenz von Options +SymLinksIfOwnerMatch sind, ansonsten wäre das ein sensiblerer Default, der dann schon mit unserer bisherigen Config funktioniert hätte und auch mit der aktuellen funktioniert, und sonst hätte man auch nicht ein Auskommentieren der Zeile als einzige Alternative darstellen müssen. Aber egal, wir wollen nicht ablenken, es ist nur ein Beispiel dafür, dass es damit unsererseits auch noch weiteren Handlungsbedarf gab, als einfach nur die AllowOverride-Policy zu ändern.

Die Sache mit der Anpassung von .htaccess-Dateien

Wir haben lange im Team diskutiert, ob wir die betreffenden User lediglich informieren und ihnen dabei ggf. auch direkt erklären, was sie tun müssen. Das wäre nicht zuletzt aus Privatsphäregründen sicherlich die wünschenswertere Option gewesen, denn ungefragt an Dateien in User-Accounts herumzufuhrwerken, entspricht wirklich nicht unseren üblichen Maßstäben. Dass wir letztlich doch diesen Schritt gegangen sind, liegt an dem Preis, der dafür zu zahlen gewesen wäre, denn: Eine Information im Sinne von „Du musst hier dieses und jenes ändern, sonst geht am Tag X deine Site kaputt“ braucht Vorlauf, und da reden wir nicht von einem Tag, sondern wenigstens von einer Woche, oder vielleicht auch gleich vier Wochen, denn möglicherweise ist der betreffende User ja gerade in Urlaub und möchte sicherlich nicht zurückkehren und feststellen, dass seine Site seit drei Wochen nicht mehr läuft. Es wäre aber nun wirklich fahrlässig gewesen, eine derart lange Zeit einen uns zu jenem Zeitpunkt dann ja nun bereits bekannten Angriffsvektor einfach bestehen zu lassen. Es gab also im Wesentlichen drei Möglichkeiten für uns:

  1. Wir informieren die User, deren Sites Options +FollowSymLinks einsetzen, was sie tun müssen, damit ihre Site bei der Umstellung nicht kaputtgeht, und lassen die Sicherheitslücke sehenden Auges für ein gewisses Zeitfenster offen. Das geht irgendwie gar nicht.
  2. Wir informieren die User, deren Sites Options +FollowSymLinks einsetzen, was sie tun müssen, und fixen die Sicherheitslücke aber sofort. Die betreffenden Sites sind dann erstmal kaputt, bis die User dem Inhalt der Mail folgen. Das wäre für die betreffenden User sehr ärgerlich.
  3. Wir ändern bei den Usern, deren Sites Options +FollowSymLinks einsetzen, die Einstellung in Options +SymLinksIfOwnerMatch, deren Sites damit weiterhin funktionieren, und schließen die Lücke sofort. Das ist technisch top, aber privatsphärentechnisch nur schwer akzeptabel.

Alle drei Lösungen sind mehr oder weniger unschön; die letzte eben vornehmlich wegen des zuvor nicht explizit vom Eigentümer der jeweiligen Datei autorisierten Schreibzugriffs. Wir sind nach längerer Diskussion im Team aber letztlich einvernehmlich zu dem Schluss gekommen, dass es von den drei Möglichkeiten diejenige darstellt, die technisch minimal-invasiv ist, weil FollowSymLinks und SymLinksIfOwnerMatch ja letztlich exakt das Gleiche tun, nur Letzteres eben mit einem zusätzlichen Sicherheitscheck, und wir insofern den Sinn der Konfiguration nicht verändern. Die Änderung wurde letztlich mittels find und sed vorgenommen, so dass wir ganz explizit nur Dateien, die definitiv „.htaccess“ heißen, überhaupt haben automatisiert anfassen lassen, um anhand dieses Ergebnisses lediglich die Vorkommnisse von FollowSymLinks durch SymLinksIfOwnerMatch zu ersetzen. Es wurden unsererseits also keine anderen Dateien auf ihren Inhalt inspiziert, weder automatisiert noch mit dem menschlichen Auge. Wir hoffen insofern sehr auf das Verständnis der betreffenden User, dass wir hier letztlich eingreifen mussten, auch wenn wir überzeugt davon sind, dass die automatisierte Anpassung letztlich – zumindest technisch gesehen – in ihrem Sinne sein müsste.

Wurde die Lücke denn ausgenutzt?

Es liegt leider in der Natur der Sache, dass das nicht nachvollziehbar ist. Ein Symlink kann angelegt und im nächsten Moment schon wieder entfernt sein; solange er nicht über einen Backup-Zyklus hinweg bestand, gibt es insofern keinen Vergleichs-Datenbestand, anhand dessen man sagen könnte: Da war so ein böser Symlink. Wenn es einen gab und dann ein HTTP-Request darauf gemacht wurde, gibt es zwar einen Eintrag im access_log der jeweiligen Site, aber dem wiederum ist nicht anzusehen, ob der auf so einen böswilligen Symlink ging.

Und nun?

Lange Rede, kurzer Sinn: Das Problem ist gefixt. Die Configs von Usern sind soweit nötig angepasst, so dass – hoffentlich – nichts Wesentliches dabei kaputtgegangen sein sollte. Für uns und unsere User liegt hiermit ein trauriger Beleg vor, dass auch wir nicht unfehlbar sind. Wir haben unser Bestes getan, so damit umzugehen, wie wir es uns selbst als User eines anderen fiktiven Hosters gewünscht hätten, und hoffen darauf, dass das aus Sicht der meisten User auch das Richtige war. Letztlich bleibt uns nur, für diesen wirklich ärgerlichen Konfigurationsfehler um Entschuldigung zu bitten.

34 Antworten auf „FollowSymLinks vs. SymLinksIfOwnerMatch“

  1. Hi, halb so wild – das kann passieren. Danke für die ausführliche Erklärung! Ihr habt alles richtig gemacht! Das ist ein Beweis dafür, dass ich beim richtigen Hoster hoste 🙂

  2. Danke für den ausführlichen Beitrag!

    Ich verstehe das shadow und die htaccess Umgehungsproblematik. Klar ist mir aber nicht, wie das lesen per Apache Daten revealen würde.

    Beispiel der config.php – jemand weiss dass ein User auf der Maschine so eine Datei hat und konstruiert den Pfad darauf. Dann muss er per http doch die URL des Symlinks aufrufen, und kriegt dann das PHP-geparste Ergebnis. Das ist doch dasselbe als würde man so eine Datei mit der „echten“ URL aufrufen? An den Sourcecode käme man doch gar nicht?

    1. @Garvin: Der Symlink auf eine .php-Datei muss ja nicht selbst auf .php enden … wenn du ihn auf etwas Anderes enden lässt, wie z.B. .txt, hat der Apache keinen Anlass, dafür den .php-Handler anzuwerfen.

  3. Hallo,

    an sich ist das ganze ja mit dem Blogeintrag offen dokumentiert, ich frage mich aber, warum bei Option 3 das informieren der Nutzer so explizit ausgeklammert wird. Warum nicht eine Mail nach dem Motto: „Hallo, wir mussten ändern…“?

    Das ermöglicht auch Nutzern, die nicht Twitter nutzen, das Wiki oder den Blog lesen, von diesem Eingriff zu Erfahren.

    1. @Marvin: „Explizit“ klammern wir’s ja gar nicht aus. Wir haben durchaus in Betracht gezogen, die betreffenden User auch noch per Mail anzuschreiben, uns aber letztlich dazu entschieden, die Policy-Änderung „nur“ auf sämtlichen Wegen zu kommunizieren, auf denen wir sowieso schon immer und auch ausschließlich über Entwicklungen, Veränderungen, Ausfälle oder Probleme berichtet haben – auch bei Heartbleed beispielsweise haben wir kein Rundmailing an alle User gemacht. Letztlich geht die Zahl der User, die das betrifft, in die Tausenden, und das geht vor allem auf Webapplikationen wie z.B. das genannte Joomla!-CMS zurück, wo User also ohnehin nie wissentlich FollowSymLinks aktiviert haben, nicht wissen, wofür das gut ist, und denen das im Wesentlichen auch egal ist. Wir gehen davon aus, dass User, denen sowas nicht egal ist, unseren regulären Kommunikationskanälen folgen, über die wir die Information schon ziemlich streuen. Last but not least hinterlassen wir bei einer erfolgten Änderung eine .htaccess.before-uberspace-change, die Usern im Zweifelsfall dann auch nochmal einen Anlass zur Nachfrage gäbe, wenn sie tatsächlich ansonsten nichts weiter mitbekommen haben.

  4. [i]um zumindest diesen – via Twitter öffentlich bekannt gewordenen – Angriffsvektor ad hoc zu beseitigen.[/i]

    Ich finde es aber wichtig, dass ihr solche Sicherheitslücken schon vor dem Fix uns bekannt macht. Nicht damit wir sie ausnutzen können, sondern weil alles andere ein erster Schritt Richtung NSA ist. Durch die Veröffentlichung seid ihr bestrebt das Problem so schnell wie möglich zu fixen. Das finde ich wichtig.

    1. @Patrick: „weil alles andere ein erster Schritt Richtung NSA ist“ – wie meinen? Dem kann ich wirklich nicht folgen. Erstens ist die Lücke ja bereits öffentlich bekannt geworden. Zweitens sind wir auch ohne die Veröffentlichung des Problems bestrebt, es so schnell wie möglich zu fixen. Drittens: Responsible disclosure. So machen wir das halt. Es ist ja nicht so, dass wir die Lücke verschweigen oder uns irgendwie drumherumwieseln würden; dann hätten wir’s auch bei einem verschämten kurzen Mini-Tweet lassen können. Details zu einer Lücke erst dann zu publizieren, wenn sie auch effektiv geschlossen ist, halten wir schlicht für verantwortungsvolles Handeln. Ein „Hey, da gibt’s diese Lücke, so und so kann man die ausnutzen, wir wollten dir das nur mitteilen, aber selbst tun kannst du dagegen nichts“ nützt ja nun wirklich niemandem.

  5. Um zu sehen, was betroffen ist:
    $ find /var/www/virtual/$USER -name „.htaccess“ -exec grep „SymLinksIfOwnerMatch“ ‚{}‘ +

    Betroffen bei mir: 1x Joomla, einmal WordPress.
    Anderer Account: kein WP betroffen, Contao auch nicht.

    @Patrick:
    Auch ein CVE wird erst veröffentlicht, wenn wenigstens ein Patch verfügbar ist. Ich finde das Vorgehen schon richtig so. Was ist, wenn so ein Fix mal mehrere Tage dauert? Dann wäre das -erst-veröffentlichen- gar nicht mehr so lustig, weil dann dein Konto ungeschützt ist.

  6. Es ist auch alles halb so schlimm, solange diese offene Kommunikationspolitik gerade auch bei solchen kritischen Bereichen beibehalten wird. Danke für die Meldung 🙂

  7. @Jonas:
    Ich finde euer Verhalten ja richtig, zuerst sagen dass es eine Sicherheitslücke im Produk XX gibt, dann dieses sicherheitshalber deaktivieren, dann fixen und dann optimalerweisse noch die Details veröffentlichen.

    Ich wollte euch nur sagen, dass ihr so weitermachen solltet und nicht damit beginnen solltet Sicherheitslücken (wenn ihr sie entdeckt und niemand sonst es Öffentlich gemach hat) zu ignorieren oder sogar zu verschweigen und erst dann eine Lösung zu entwickeln wenn jemand die Lücke bemerkt.

  8. Danke für den offenen Umgang mit dem Problem, der zügigen Reaktion und der detaillierten Erklärung. Weiter machen! Eure Arbeit hat Vorbildcharakter.

  9. geil! danke für den ausführliche eniblick in die materie! ich bin definitiv beim richtigen hoster!!! DANKE!!! 😀

  10. Geil! Besten Dank für den ausführlichen Einblick in die Materie! Ich bin definitiv beim richtigen Hoster!!! DANKE!!! 😀

  11. Vielleicht ein kleiner Hinweis, warum SymlinksIfOwnerMatch beim Apache nicht Standard ist: Apache wird nicht nur im Shared-Hosting-Bereich eingesetzt. Dort ist SymlinksIfOwnerMatch richtig und gut. Ist man allerdings auf dem Rechner als „Kunde“ alleine, verschenkt SymlinksIfOwnerMatch Performance, weil Apache bei jedem Request den Eigentümer prüfen muss und das Ergebnis nicht gecached werden kann und darf (Stichwort lstat-Syscall).
    Die Apache-Entwickler wissen das und versuchen, bei der Default-Config eine Mischung aus Performance und Sicherheit zu finden. Wenn man sich der Problematik als Admin bewusst ist, ist das – wie hier – aber schon einmal die halbe Miete.

  12. Wieso muss der Apache auf die /etc/shadow lesen können, um sie für die webalizer-Authentifizierung verwenden zu können? Ich kenne zwar euer Setup nicht, aber Module wie mod_auth_pam erledigen das über die pam-Infrastruktur, wo der Anwender nicht auf die shadow zugreifen muss.

    Ein weiterer Angriffsvektor war vermutlich zu versuchen .htaccess-Dateien zu abzugreifen und deren Passwörter zu bruteforcen, zumal da gerne schwächere Algorithmen verwendet werden.

  13. Sorry, stimmt, hatte es falsch in Erinnerung – ich shciebs auf die Nacht 😉

    Als Kleine Entschädigung: es gibt pwauth ( http://icephoenix.us/linuxunix/apache-and-http-authentication-with-pam/ / https://code.google.com/p/pwauth/w/list ), wodann nur ein kleines Programm und nicht gleich der ganze Apache auf die shadow zugreifen können muss.

    Mir sind noch zwei weitere mögliche Angriffsmöglichkeiten eingefallen: und zwar Aliase per .htaccess (falls Zugriff auf den VirtualHost-Abschnitt besteht) und ServerSideIncludes.

    Der letzte Abschnitt kann vor der Moderation gerne abgeschnitten werden, falls es zu „heiß“ ist 😉

    1. @mifritscher: „Aliase per .htaccess“? Die Alias-Anweisung ist in .htaccess-Dateien doch gar nicht möglich … 😉 Zugriff auf den VirtualHost-Abschnitt besteht nicht. Server Side Includes führen Code via suEXEC aus, der dann mit den Rechten des Users und nicht mit den Rechten des Apaches läuft.

  14. Sorry, irgendwie muss das beim Korrekturlesen durchgerutscht sein… Ich wollte Apache-Konfigration schreiben, auf desen VirtualHost-Abschnitte ich mich bezog. VirtualHosts gehen in .htaccess-Dateien ja noch viel weniger 😉

  15. Eine Quelle für „Options +FollowSymLinks“ ist die Doku von mod_rewrite, die das so fordert.

    Hilfreich wär ein Kommentar in der geänderten .htaccess mit Link hierher gewesen, aber mir ist klar, dass das auch das Risiko erhöht, sie zu zerschießen, wenn man sie nicht alle manuell sichten will oder (wegen der Menge) kann. Wegen der Privatsphäre hätt ich da kein Problem; das ist ein technisches Dokument, das für solche Zwecke zugänglich sein muss.

    Beim nächsten Mal wär es aber nett, wirklich nur die Dateien zu touchen, die geändert werden müssen, damit nicht lauter uralte .htaccess-Dateien und Verzeichnisse als neu erscheinen.

    Das mit dem Webalizer-Zugriff hab ich schon vorher für eine Fehlkonstruktion gehalten. Extra dafür ein Systempasswort zu erzwingen, ist Overkill. Die meisten Statistiken werden wohl eh bloß fürs Nirvana produziert. Könnte man auch nur auf Anforderung produzieren und die Benutzer dann selber um einen Schutz kümmern oder ein separates Passwort setzen lassen. Ob es sinnvoll ist, das bestehende System nachträglich zu ändern, ist allerdings eine andere Frage.

  16. Hi,

    ich wollte euch (und dem User, welche die Lücke entdeckt hat) hiermit meinen Dank zollen, da ich mit meinem jetzigen Wissen diese Lücke definitiv nicht entdeckt hätte.
    Zudem sind wir bei euch, damit wir eure Dienste nutzen, also Ihr für unsere Sicherheit sorgt – und aus dieser Sichtweise gesehen habt Ihr eure Arbeit sorgsam überlegt, abgewegt und letztendlich richtig entschieden!

    Ich hoffe, dass Ihr so bleibt wie Ihr seid und dass es Uberspace noch lange geben wird.
    Mit freundlichen Grüßen, Sören Klein.

  17. Schade eigentlich…,

    … dass nicht alle Unternehmen so transparent mit Kunden umgehen wie ihr das tut.
    Euch ist sicher kein Vorwurf zu machen, dass ihr diese Lücke nicht gesehen bzw. berücksichtigt habt. Auch mit der Wahl die htaccess Dateien automatisch anzupassen seid ihr meiner Meinung nach den richtigen Weg gegangen. Auch wenn ich von der Änderung nicht betroffen war, so fasse ich meinen Uberspace teilweise über mehrere Wochen hinweg nicht an. Auch meine Uberspace E-Mails lasse ich mir nicht weiterleiten und hätte von daher garnicht erst von dem Problem erfahren (oder erst wenn es zu spät gewesen wäre).

    Euer Dienst ist großartig und ich hoffe dass er auch weiterhin Bestand hat!

    Viele Grüße =)

  18. Hi,

    Ich finde auch, daß die Vorgangsweise beim dem fix völlig in Ordnung war. Danke dafür!

    Ich finde aber auch, daß eine Info-mail an die betroffenen User die eine Zeile extra Code nach find+sed wert gewesen wäre. 😉

    Dann wäre ich nicht nur nebenbei über diese Info gestolpert, weil ich zufällig auf der Suche nach etwas völlig anderem jonaspasche.com direkt angesurft habe.

    Bitte nicht falsch verstehen: Die Überlegungen, die Ihr angestellt habt um den perfekten Kompromiss zwischen Sicherheit und Euren Prinzipien zu finden sind schon weit mehr als manch anderer Hoster tun würde. Aber gerade dieses (wirklich hochgeschätzte!) Prinzip „Userdaten sind tabu“ hätte eigentlich zu dem Schluss führen müssen, „wenn wir schon damit brechen müssen, sollten wir es ihnen direkt sagen.“ Ein Link hierher hätte dabei genügt.

    Vielleicht nur so als Vorschlag für’s nächste Mal 😉

    Trotzdem danke für Euren stets tollen Einsatz!

    Fredl.

  19. +1. Auch ich unterstütze Eure Aktion, denke aber, eine Mail wäre nett und auch notwendig, aus einem ähnlichen Grund, weshalb Ihr Option 3 gewählt habt:

    Wenn jemand ein Backup einer Seite ausgräbt (oder einen andere branch per git hochlädt, oder eine bekanntermaßen funktionierende Konfiguration auf die Server schiebt, oder…), in der eine „gefährliche“ .htaccess ist, ist seine vormals funktionierende Seite plötzlich hinüber. Und möglicherweise an einer Stelle, die man nicht auf Anhieb entdeckt.
    Und dann sollte er hoffentlich nicht in Urlaub fahren, nachdem er den letzten jetzt defekten stable-Stand hochgeladen hat, Minuten nachdem Ihr die WIP-Version automatisch gefixt habt…

    Gruß
    Alexander

    1. Hi Alexander, wir haben inzwischen einen Job, der FollowSymlinks in .htaccess-Dateien automatisch in SymLinksInOwnerMatch korrigiert und dabei dann auch eine Informationsmail versendet. Wer also z.B. nochmal ein Backup hochlädt, bekommt das sofort korrigiert und kriegt auch gleich die Info dazu.

  20. Moin,

    ich bin selbst gerade drauf reingefallen und war mehr als begeistert von der Autokorrektur per Job und der darauf folgenden Infomail.

    Als langjähriger Entwickler hasse ich es eigentlich, wie die Pest, wenn mir jemand in meiner Konfiguration oder Entwicklung rumfuhrwerkt. Aber in diesem konkreten Fall, den ich schlichtweg übersehen habe und der absolut reibungslosen und vor allem komplikationsfreien Behebung meines eigenen Konfigurationfehlers bin ich vollends begeistert. Das ist genau der Service den ich mir im Falle von Sicherheitslücken von meinem Hoster wünsche. Ich habe mittlerweile meinen zweiten Uberspace registriert und bin sehr Happy darüber, dass Du Jonas und deine Kollegen hier solch ein großartiges Angebot mit einem derart großartigen Service – vor allem im Troubleshooting auf die Beine gestellt habt. Ich bin echt kein Fan von unnötigem „gehype“ aber bei euch ist es einfach richtig platziert.

    Danke für eure Arbeit!
    Julian

    1. Wenn das so einfach wäre, wäre das schön. Ich bin schon einigermaßen konsterniert, dass der Apache da eine lange bekannte Race Condition hat und das aber offenbar nicht als zu fixenden Bug betrachtet, weil’s ja in der Doku steht, dass es den gibt. „Eine httpd-Version, in der keine TOCTOU Race-Condition beim Symlink-Check mehr enthalten ist“ existiert insofern nicht: Alle Apache-Versionen haben diesen Bug. Das Writeup ist uns wohlbekannt, und wir haben auch nahezu alles davon evaluiert. mod_ruid+jailshell: jailshell ist eine proprietäre Erweiterung von cPanel; steht nicht zur Verfügung. CageFS: auch nur für cPanel. GRSec: Das wäre halt ein ziemlicher Aufriss mit kaum überschaubaren Nebeneffekten, den von Red Hat gepflegten Enterprise-Kernel durch einen ganz anderen Kernel in ganz anderer Version zu ersetzen. RHEL-Kernel mit GRSec gibt es meines Wissens nach nicht. mod_hostinglimits ist CloudLinux-exklusiv. Der Bluehost-Patch erscheint uns noch am vielversprechendsten und dabei minimal-invasivsten, und wir arbeiten schon länger daran, den irgendwie gegen das Source-RPM des Apaches von CentOS 5 und 6 zu bauen, was aber partout nicht rund läuft. Der Rack911 ist nett und hätte uns den oben beschriebenen Aufriss erspart, in den Configs überall das FollowSymLinks zu ersetzen – fixt aber nicht die Race Condition. Unabhängig von dem Writeup hätte auch mod_itk noch gut ausgesehen, weil das quasi den ganzen VirtualHost als Zieluser bedient, nicht nur wenn’s an die Scriptausführung geht; dafür funktioniert dann aber mod_fcgid nicht mehr und damit auch PHP, was dann gar nicht mehr akzeptabel ist. Aller Voraussicht nach werden wir vermutlich vom CentOS-Apache auf einen generischen selbstkompilierten Apache mit Bluehost-Patch wechseln, sofern die dafür doch recht umfangreich durchzuführenden Tests erfolgreich verlaufen. Bis dahin müssen wir uns damit zufrieden geben, dass ein Ausnutzen der Race Condition nicht ganz trivial ist und bis zum potentiell Erfolg viele Fehler triggert, auf die dann zügig fail2ban anspringt. Das ist zwar eher die Holzhammer-Methode, aber da es halt keinen einfachen, sauberen, nebeneffektsarmen Fix gibt, muss das für den Moment reichen. Die Bluehost-Variante ist jedenfalls in Arbeit.

  21. Vielen Dank, dass ihr uns auch aus *euren* Fehlern lernen lasst. Ihr seid eine einzige Lehrveranstaltung.
    Den Bock geschossen haben sicherheitstechnisch schon lange vorher viele andere viel größere Unternehmen. Und sie tun es laufend wieder. Offene Kundendatenbanken mit nicht gesalzenen Passwörtern finde ich n büschn krasser, als den Fall mit den FollowSymLinks…
    Fetter Respekt geht mal wieder raus an: Uberspace!

Kommentare sind geschlossen.