Das Rätsel der öffentlichen Home-Verzeichnisse

Bei Uberspace.de haben wir in der Vergangenheit immer mal wieder erlebt, dass einzelne Home-Verzeichnisse, die normalerweise nur für den Besitzer les- und schreibbar waren, plötzlich öffentlich lesbar waren:

[root@taurus ~]# ls -l /home
...
drwx------ 5 user1 user1 4096 19. Dez 11:15 user1
drwx------ 5 user2 user2 4096 16. Dez 12:32 user2
drwxr-xr-x 5 user3 user3 4096 20. Dez 15:04 user3
drwx------ 5 user4 user4 4096 20. Dez 11:25 user4
drwx------ 5 user5 user5 4096 15. Dez 13:09 user5
...

Anfangs haben wir, wann immer uns das auffiel, die Rechte entsprechend korrigiert und den User informiert – und in keinem einzigen Fall bekamen wir die Rückmeldung, dass ein User die Rechte tatsächlich selbst so geändert hatte; vielmehr waren alle bass erstaunt, wie so etwas passieren konnte.

Nun ist diese Änderung nicht so schlimm, wie es auf den ersten Blick aussehen mag, denn die meisten sensiblen Daten, beispielsweise Mails, sind auch innerhalb des Home-Verzeichnisses nur für den Eigentümer selbst lesbar, und beispielsweise PHP-Scripts, die MySQL-Zugangsdaten erhalten, liegen im DocumentRoot, der ohnehin außerhalb von /home liegt und von daher nicht betroffen ist. Aber natürlich gibt es potentiell immer noch viele Möglichkeiten, so an Informationen zu gelangen, die niemanden etwas angehen – wenngleich nicht aufgrund einer Sicherheitslücke, denn wir setzen die Rechte ja durchaus korrekt und strikt auf 700, und „von alleine“ ändern sie sich nun mal nicht: Es muss also irgendwas sein, was von den betreffenden Usern selbst ausgelöst wird, und zwar höchstwahrscheinlich versehentlich.

Unsere eigenen Tools haben wir zügig kontrolliert und konnten schon nach kurzer Zeit mit an Sicherheit grenzender Wahrscheinlichkeit ausschließen, dass eins von denen für das Problem verantwortlich zeichnete. Parallel dazu artete die periodische manuelle Kontrolle mit der Zeit in echte Arbeit aus, so dass wir kurzerhand beschlossen, ein Script zu schreiben, das die Rechte alle paar Minuten prüft, automatisiert fixt und den betreffenden User eine Mail sendet, einerseits mit dem Hinweis auf die Korrektur, andererseits aber auch mit der Bitte, uns doch mitzuteilen, was sie in den letzten paar Minuten so getan hatten, um einige Hinweise zu erlangen, wie diese plötzliche Rechteänderung denn nun eigentlich genau passieren kann.

Nach einigen Rückmeldungen verdichteten sich die Hinweise darauf, dass es etwas mit npm zu tun haben könnte, dem Paketmanager von node.js – aber es war schwierig, den Effekt zu reproduzieren: Zeitweise schien es, als würde der Effekt nur bei der Installation ganz bestimmter Module auftreten; aber auch hier trat der Effekt nicht verlässlich auf. Weder die betreffenden User noch wir hatten zunächst in Betracht gezogen, dass es daran liegen könnte, in welchem Verzeichnis man sich befindet, während man npm install ... ausführt.

Ein kleiner Exkurs.

Für praktisch jede Scriptsprache gibt es auch Tools, mit dem zusätzliche Module heruntergeladen und installiert werden können – und das Konzept ist im Grunde immer gleich. Um ein paar Beispiele zu nennen:

  • PHP hat PEAR und installiert Module in das Verzeichnis, das in der ~/.pearrc dafür angegeben wird.
  • Perl hat CPAN und installiert Module in das Verzeichnis, das via PREFIX über die CPAN::MyConfig angegeben wird.
  • Python hat easy_install und pip und installiert Module in das Verzeichnis, das in der distutils.cfg angegeben wird.
  • Ruby hat RubyGems und installiert Module in $HOME/.gem.

Ist hier möglicherweise ein Muster erkennbar? Ich denke doch.

Das Problem ist nun, dass node.js und npm hier ein ganz anderes Konzept verwirklichen. Hier wird ein Verzeichnis node_modules im Verzeichnis der Applikation angelegt, in dem die zu installierenden Module landen. Entwickelt man also unter ein und dem selben Linux-User mehrere node.js-Applikationen, so müssen die gewünschten Module für jede Applikation separat installiert werden. Ja, ich habe da selbst erstmal daran gezweifelt, aber der npm-Autor führt ganz konkret aus:

[…]
Install it in both places. Seriously, are you that short on disk space? It’s fine, really. They’re tiny JavaScript programs.
[…]
The first option is the best in my opinion. Simple, clear, explicit.
[…]

npm hat nun die Eigenschaft, beim Anlegen von Verzeichnissen jene automatisch mit chmod 755 zu behandeln. Im Oktober 2011 kam noch eine Option dazu, um eine umask zu setzen, die dies anpassbar macht, aber 755 ist weiterhin der Default. Das Problem ist nun, dass npm auch bei bereits bestehenden Verzeichnissen sicherstellt, dass jene die vorgegebenen Rechte bekommen.

Und hier liegt letztlich der Hund begraben. npm hat nämlich eine dokumentierte Logik, wohin genau es Module installiert. Man muss sich nämlich nicht zwingend im Applikations-Root-Verzeichnis befinden, sondern kann auch in einem Unterverzeichnis davon sein: npm hangelt sich dann so lange verzeichnisweise nach oben, bis es ein Verzeichnis findet, das ein Unterverzeichnis node_modules beinhaltet, und betrachtet jenes Verzeichnis dann als den Applikations-Root. Dumm ist das nicht:

This behavior is inspired by and similar to git’s .git-folder seeking logic when running git commands in a working dir.

Problematisch wird es dann, wenn es kein Verzeichnis node_modules gibt. In diesem Fall sieht npm nämlich das aktuelle Verzeichnis als Applikations-Root an – und wenn man also während der Installation gerade zufällig in seinem Home-Verzeichnis ist, bekommt jenes ein harsches chmod 755 ab. So sieht das in der Praxis aus:

[dummy@lyra ~]$ ls -ld ~
drwx------ 16 dummy dummy 4096 Dec 30 11:25 /home/dummy

[dummy@lyra ~]$ npm install fibers --verbose
...
npm verb mkdir done: /home/dummy 755
...

[dummy@lyra ~]$ ls -ld ~
drwxr-xr-x 16 dummy dummy 4096 Dec 30 11:25 /home/dummy

Insofern ist dieses Verhalten insbesondere für User gefährlich, die sich mit dem node-Konzept applikationsspezifischer node_modules-Verzeichnisse noch nicht vertraut gemacht haben und es schlicht und einfach von PHP, Perl, Python, Ruby oder irgendeiner anderen Sprache gewohnt sind, dass es keine Rolle spielt, in welchem Verzeichnis man sich gerade befindet, wenn man Module installiert. Auch andere Bugreports zeigen, dass wir und unsere User nicht die einzigen sind, die über dieses Verhalten stolpern.

Als schnellen Workaround haben wir nach unserer Analyse im Uberspace-Wiki dokumentiert, dass es eine gute Idee ist, umask = 077 in seine ~/.npmrc aufzunehmen – auf diese Weise passiert das chmod zwar immer noch, richtet aber keinen Schaden mehr an – und für die Ausführung der node.js-Applikationen ist es zumindest bei Uberspace.de auch nicht vonnöten, dass noch jemand anders als der Eigentümer selbst auf die Applikation zugreifen kann.

Parallel dazu haben wir einen Bugreport verfasst, der dieses Problem thematisiert – und wie es aussieht, wird das in künftigen npm-Versionen dann erfreulicherweise anders laufen. Danke an Nils für seine wichtigen Hinweise; an Peter für seine tatkräftige Unterstützung beim Debugging; und an Isaac für das schnelle Feedback.

Eine Antwort auf „Das Rätsel der öffentlichen Home-Verzeichnisse“

  1. Schön, dass Ihr Euch bei so etwas solche Gedanken macht und dann auch eine Lösung an Upstream weitergebt!

Kommentare sind geschlossen.