Proftpd Bugfix macht Login unmöglich

Die späte Rache ereilte vermutlich die Entwickler vom allseits beliebten FTP-Server Proftpd. Um das Problem zu verstehen muß man etwas ausholen und in die Vergangenheit des Servers zurückgehen:

Spätestens im Jahr 1999 wurde mit der Version 1.2.0pre9 die Funktion eingebaut, daß FTP-Benutzer die einloggen, in einer Chroot gefangen werden, damit sie nur auf ihr Homeverzeichnis zugreifen können. Die Option hies „DefaultRoot“. In der Doku zu der Option findet sich folgender Hinweis:

When the specified chroot directory is a symlink this will be resolved to it’s parent
first before setting up the chroot. This can have unwanted side effects. For example if
a user has write access to the symlink he could modify it so that it points to ‚/‘

Meint auf Deutsch in Kurzform, daß wenn das Homeverzeichnis eigentlich ein Symlink ist, diesem gefolgt wird und das, wo der rauskommt, das neue „/“ von der Chroot ist.

Im Klartext: wenn  /home/testuser ein Symlink auf  „/“  ist, dann ist der User nicht in /home/testuser gefangen, sondern kann sich frei im normalen „/“ Verzeichnis rumtreiben. Ein Sicherheitsloch, daß locker mal 20 Jahre existiert hat.

Die FAQ von Proftpd meint zu dem Thema Chroot, daß man als Admin gefälligst dafür Sorgen soll, daß User das nicht anlegen/ändern können und halt kein Sicherheitsloch entstehen soll. Die schoben die Verantwortung also an die Admins weiter, was zu einem bestimmten grad ok war, aber dann darf man andere Sachen gar icht erst erlauben.

Mein Teil an der Story

In 2012 habe ich den Entwicklern von Proftpd einen Patch für proftpd geschickt, der genau dies Problem adressiert hat und keine Nebenwirkungen hatte. Der Patch prüft bei jedem Zugriff, ob sich in dem Pfad ein Symlink eingenistet hatte. So konnte es keine RACE Condition geben, bei der der Benutzer durch schnelles löschen und SymLink anlegen, die Sicherungsmaßnahmen umgehen konnte. Kurzfassung: Der Patch wurde mit : „Nicht unser Problem, siehe FAQ “ abgelehnt. Was sich jetzt als tragisch herausstellt. Besonders tragisch, da für den 29C3 in 2012 ein Vortrag zu dem Thema von mir eingereicht wurde.

Das Jahr 2016

In 2016 hat es dann endlich jemand geschafft, die Entwickler zu einer Option zum Checken von Symlinks im Pfad zu nötigen. Herzlichen Dank dafür, keine Ahnung wie Du das geschafft hast! Klasse!

Das Jahr 2017

Nun konnte ja nicht sein, was nicht sein durfte, in der Routine zum Checken der Symlinks wurde ein Sicherheitsloch entdeckt ( Hämischer Kommentar: Told you so ! ) und diesem wurde die CVE-2017-7418 zugeteilt.

Nun gabs es dieser Tage den Patch zu dieser Lücke im Server und damit das obligatorische Update auf den Produktivsystemen. Keine große Sache, sollte man denken. Tja, wer hat es geraten ? Auch diese Routine failed. Die hat das Sicherheitsproblem auf einer völlig neuen Ebene gelöst: Es kann sich kein Virtueller FTP-User mehr einloggen 😀

Ursache ist das hier:

[pid 32571] setresgid(-1, 99, -1)       = 0
[pid 32571] setresuid(-1, 99, -1)       = 0
[pid 32571] setresuid(-1, 0, -1)        = 0
[pid 32571] setresgid(-1, 1001, -1)     = 0
[pid 32571] setresuid(-1, 1000, -1)     = 0
[pid 32571] lstat("/", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
[pid 32571] lstat("/opt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 32571] lstat("/opt/root", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 32571] lstat("/opt/root/home", {st_mode=S_IFDIR|0755, st_size=20480, ...}) = 0
[pid 32571] lstat("/opt/root/home/testuser", {st_mode=S_IFDIR|0750, st_size=4096, ...}) = 0
[pid 32571] lstat("/opt/root/home/testuser/public_html", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
...
[pid 32571] geteuid()                   = 1000
[pid 32571] setresuid(-1, 0, -1)        = 0
[pid 32571] setresgid(-1, 99, -1)       = 0
[pid 32571] setresuid(-1, 99, -1)       = 0
[pid 32571] setresuid(-1, 0, -1)        = 0
[pid 32571] setresgid(-1, 0, -1)        = 0
[pid 32571] setgid(1001)                = 0
[pid 32571] geteuid()                   = 0
[pid 32571] setresgid(-1, 99, -1)       = 0
[pid 32571] setresuid(-1, 99, -1)       = 0
[pid 32571] lstat("/opt/root/home/testuser/public_html", 0x7ffee3d84dd0) = -1 EACCES (Permission denied)

Für die Laien unter Euch, das ist der Auszug eines STRACE Logfiles. Darin finden wir alle Befehle die der Prozess ausgeführt hat ( API-Calls , nicht Bashkommandos 😉 ) . Man sieht deutlich das im ersten Block mit einer UID/GID von 1000/1001 auf das Homeverzeichnis des Benutzers zugegriffen wird, weil der Prozess entsprechend seine UID/GID ändert. Das ist RICHTIG so.

Was falsch ist, daß er das nicht auch beim zweiten Block tut. Hier ist die UID des Prozesses (proftpd) statt 1000, nur 99, was dem User NOBODY entspricht. Das ist der User, zu dem Prozesse werden sollen um Ihre Rechte zu verlieren um im Falle eines Sicherheitsbruches den Schaden zu begrenzen. (@Team: Der Teil hat 1a funktionert. Ohne Logins keine Bedrohung mehr) . Natürlich müßte auch hier die UID/GID auf 1000/1001 gesetzt werden, damit man an seine Dateien rankommt, denn normalerweise haben Verzeichnisse wie „/home/testuser“ einen chmod von 700, damit nur der User drankommt.

20 Jahre bis Problem akzeptiert. 4 Jahre bis zum Fix und nur 6 Monate bis zum Totalausfall der Server. Eine Glanzleistung sonders gleichen. Hätte man meinen Patch in 2012 nicht todgeredet, wäre uns das erspart geblieben 🙂 Da der Vortrag abgelehnt wurde, ging das Thema am 29C3 leider unter und so könnten die Jungs und Mädels vom CCC unabsichtlich auch dran beteiligt gewesen sein 😉  Tja, so ist das Leben.

Kleiner Disclaimer:

Es hängt ein bisschen von der Serverkonfiguration ab. Wer keine Datenbank benutzt, sondern nur reale User, der hat das Problem den bisherigen Infos nach nicht. Wer „AllowChrootSymlinks on“ aktiviert hat ( was der Default ist) hat auch kein Problem mit dem Login, wohl aber mit dem Umstand, daß er/sie ein angreifbares System hat ( siehe oben ) das ganz schnell gehackt werden kann.

 

Über den Sinn und Unsinn von MD5 Checksummen auf Webseiten

Es war einmal vor einigen Tagen, … okok, es war heute, ich poste den Beitrag nur später… ähähämm .. nochmal… es war einmal ein junger Stern am Kryptohimmel. Sein Name war MD5 und er war von der Rasse der Hashe, die aus dem Land der Algorithmen stammten. Unser junger Stern wuchs schnell zu einem ganz großen Hash heran, der für viele Dinge der Menschen seinen Schutzzauber sprach und so für Ihre Sicherheit sorgte.

Eines Tages kam ein Sprößling der Gattung Mensch, aus der Rasse der Distributoren, auf die Idee, doch seine digitalen Datenrohlinge von unserem jungen Stern vor Veränderungen schützen zulassen,  so daß jeder erkennen mag, daß er eine Fälschung den digitalen Fluß hinabschifft.

Am Beispiele der Slacks soll hier gezeigt werden, wie er es anstellte :

Parent Directory
slackware64-14.2-install-dvd.iso30-Jun-2016 23:222.6G
slackware64-14.2-install-dvd.iso.asc30-Jun-2016 23:22181
slackware64-14.2-install-dvd.iso.md530-Jun-2016 23:2267
slackware64-14.2-install-dvd.iso.txt30-Jun-2016 23:21198K

Unser mächtiger Stern sprach einen Schutzzauber über den jungen Datenrohling aus und dieser wurde zusammen mit dem jungen Datenrohling in sein Netz gelegt. Nun konnte jedermann, der den Datenrohling inne hatte prüfen, ob es der echte Datenrohling war, oder nur eine böse Fälschung ins Nest gelegt worden war.

Die Jahre gingen ins Land und unserer mächtiger Stern wurde alt und gebrechlich. Seine Schutzkräfte liessen nach und dennoch wandten sich die Menschen an ihren einst so mächtigen Stern und erbaten seinen Schutzzauber. Ein junger, mächtigerer Stern aus der Rasse der Hashe, stiess unseren altern Stern von seinem Throne und erfüllte den Menschen füderan ihre Schutzwünsche; sein Name: SHA256.

Es war eine Zeit in Aufruhr, denn böse Mächte unter den Menschen brachen in die Datenhorte derer ein, welche die Datenrohlinge für das Gute schufen und tauschten diese gegen billige Fälschungen aus Fernost aus. Ein Hort nach dem anderen wurde heimlich aufgebrochen und infiltriert, und dennoch legten die Menschen weiterhin Ihren Schutzzauber einfach in den Datenhort Ihres Datenrohlings, denn sie vertrauten darauf, daß sie klüger waren, als die Bösen unter ihnen.

Eines Tages geschah das Unfassbare: Ein Mensch forderte den alten Stern auf, einen Schutzzauber für seinen Datenrohling zu sprechen und unser alter Stern, sprach den Zauber aus, und die Menschen legten den Zauber wie immer zu Ihrem Datenrohling, oder nicht ? Nein! Denn der Mensch war böse und hatte den guten Zauber für seine Fälschung erbeten. Da der alte Stern alt und gebrechlich war, erkannte er dies nicht und so konnte der Mensch seine Fälschung in einen infiltrierten Datenhort geben und den guten Schutzzauber dazu legen, ganz wie es die guten Menschen mit Ihren Datenrohlingen taten.

Ein böser Fluch kam über die Datenschiffer und alle diejenigen, die diese Datenrohlinge in Ihre Bratenröhre schoben. Die Menschen wandten sich an die Distributormenschen und diese verstanden die Welt nicht mehr. Genau deswegen hatten Sie doch den Schutzzauber zu Ihrem Rohling gelegt, auf daß die Schiffer vorher erkannten, das Ihrer echt war und der andere nicht. Der Datenrohling war nicht ihrer, ja, aber der Schutzzauber hätte das doch zeigen müssen!

Doch erst  dann, als es zu spät war, erkannten Sie Ihren Fehler: Sie hätten Ihren Schutzzauber in einen anderen Datenhort ablegen müssen, der nicht vom Bösen infiltriert gewesen ist.

Darum liebe Kinder merkt Euch: Digitale Signaturen und das damit signierte Datenpaket aus der gleichen gebrochenen Datenquelle zu vergleichen, ist komplett sinnlos. Signaturen, egal, ob alt und gebrechlich 😉 , gehören auf ein logisch nicht mit dem Datenfile zusammenhängenden anderen Datenspeicher, der anders abgesichert ist, als der für das signierte Datenfile.

Man darf weiterhin behaupten, es wäre eine gute Idee, keine gebrochenen Hashalgorithmen mehr zu benutzen. Aber das ist eine andere Geschichte.