Root-Schwachstelle im Linux-Kernel und Denial-of-Service in systemd

Sicherheitsforscher von Qualys haben Details zu zwei Schwachstellen enthüllt, die den Linux-Kernel und den Systemmanager systemd betreffen. Eine Schwachstelle im Kernel (CVE-2021-33909) ermöglicht es einem lokalen Benutzer, durch Manipulation stark verschachtelter Verzeichnisse eine Codeausführung mit Root-Rechten zu erreichen.

Die Gefährlichkeit der Schwachstelle wird dadurch verschärft, dass die Forscher funktionierende Exploits vorbereiten konnten, die in der Standardkonfiguration auf Ubuntu 20.04/20.10/21.04, Debian 11 und Fedora 34 funktionieren. Es wird darauf hingewiesen, dass andere Distributionen nicht getestet wurden, theoretisch aber ebenfalls anfällig für das Problem sind und angegriffen werden können. Es wird versprochen, dass der vollständige Code der Exploits veröffentlicht wird, sobald das Problem überall beseitigt ist. Derzeit ist jedoch nur ein Prototyp mit eingeschränkter Funktionalität verfügbar, was zum Absturz des Systems führt. Das Problem besteht seit Juli 2014 und betrifft Kernel-Releases ab 3.16. Der Schwachstellen-Fix wurde mit der Community abgestimmt und am 19. Juli in den Kernel übernommen. Die Hauptdistributionen haben bereits Updates für ihre Kernelpakete generiert (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch).

Die Sicherheitslücke wird dadurch verursacht, dass das Ergebnis einer size_t-zu-int-Konvertierung nicht überprüft wird, bevor Vorgänge im seq_file-Code ausgeführt werden, der Dateien aus einer Folge von Datensätzen erstellt. Wenn die Prüfung nicht durchgeführt wird, kann es beim Erstellen, Mounten und Löschen einer sehr verschachtelten Verzeichnisstruktur (Pfadgröße größer als 1 GB) zu außerhalb der Grenzen liegenden Schreibvorgängen in den Puffer kommen. Dadurch kann ein Angreifer erreichen, dass eine 10-Byte-Zeichenfolge „//deleted“ mit einem Offset von „-2 GB – 10 Bytes“ geschrieben wird und auf den Bereich unmittelbar vor dem zugewiesenen Puffer verweist.

Für den Betrieb des vorbereiteten Exploits sind 5 GB Speicher und 1 Million freie Inodes erforderlich. Der Exploit funktioniert durch den Aufruf von mkdir(), um eine Hierarchie von etwa einer Million Unterverzeichnissen zu erstellen und so eine Dateipfadgröße von mehr als 1 GB zu erreichen. Dieses Verzeichnis wird über bind-mount in einem separaten Benutzernamensraum gemountet, woraufhin die Funktion rmdir() ausgeführt wird, um es zu entfernen. Parallel dazu wird ein Thread erstellt, der ein kleines eBPF-Programm lädt, das in der Phase nach der Überprüfung des eBPF-Pseudocodes, aber vor seiner JIT-Kompilierung blockiert wird.

Im unprivilegierten Benutzer-ID-Namensraum wird die Datei /proc/self/mountinfo geöffnet und der lange Pfadname des bindgemounteten Verzeichnisses gelesen, was dazu führt, dass die Zeichenfolge „//deleted“ in den Bereich vor dem Start des Puffers geschrieben wird. Die Position zum Schreiben der Zeile wird so gewählt, dass sie die Anweisung im bereits getesteten, aber noch nicht kompilierten eBPF-Programm überschreibt.

Als nächstes wird auf der eBPF-Programmebene unkontrolliertes Schreiben außerhalb des Puffers durch Manipulation der BTF- und Map_push_elem-Strukturen in eine kontrollierte Fähigkeit zum Lesen und Schreiben in andere Kernelstrukturen umgewandelt. Dadurch ermittelt der Exploit den Speicherort des modprobe_path[]-Puffers im Kernel-Speicher und überschreibt den darin enthaltenen Pfad „/sbin/modprobe“, wodurch Sie im Falle eines Fehlers den Start jeder ausführbaren Datei mit Root-Rechten initiieren können request_module()-Aufruf, der beispielsweise beim Erstellen eines Netlink-Sockets ausgeführt wird.

Forscher stellen mehrere Problemumgehungen bereit, die nur für einen bestimmten Exploit wirksam sind, das Problem selbst jedoch nicht beseitigen. Es wird empfohlen, „/proc/sys/kernel/unprivileged_userns_clone“ auf 0 zu setzen, um das Mounten von Verzeichnissen in einem separaten Benutzer-ID-Namespace zu deaktivieren, und „/proc/sys/kernel/unprivileged_bpf_disabled“ auf 1, um das Laden von eBPF-Programmen in den Kernel zu deaktivieren.

Bemerkenswert ist, dass die Forscher bei der Analyse eines alternativen Angriffs, bei dem der FUSE-Mechanismus anstelle von Bind-Mound zum Mounten eines großen Verzeichnisses zum Einsatz kam, auf eine weitere Schwachstelle (CVE-2021-33910) stießen, die den Systemmanager systemd betrifft. Es stellte sich heraus, dass beim Versuch, ein Verzeichnis mit einer Pfadgröße von mehr als 8 MB über FUSE zu mounten, dem Steuerungsinitialisierungsprozess (PID1) der Stapelspeicher ausgeht und er abstürzt, was das System in einen „Panik“-Zustand versetzt.

Das Problem besteht darin, dass systemd den Inhalt von /proc/self/mountinfo verfolgt und analysiert und jeden Mountpunkt in der Funktion „unit_name_path_escape()“ verarbeitet, die eine strdupa()-Operation ausführt, die die Daten auf dem Stapel und nicht im dynamisch zugewiesenen Speicher ablegt . Da die maximale Stack-Größe über RLIMIT_STACK begrenzt ist, führt die Verarbeitung eines zu großen Pfades zum Mount-Punkt zum Absturz des PID1-Prozesses und zum Stoppen des Systems. Für einen Angriff können Sie das einfachste FUSE-Modul in Kombination mit der Verwendung eines stark verschachtelten Verzeichnisses als Mount-Punkt verwenden, dessen Pfadgröße 8 MB überschreitet.

Das Problem tritt seit systemd 220 (April 2015) auf, wurde bereits im Haupt-systemd-Repository behoben und in Distributionen (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch) behoben. Insbesondere funktioniert der Exploit in Systemd-Release 248 aufgrund eines Fehlers im Systemd-Code nicht, der dazu führt, dass die Verarbeitung von /proc/self/mountinfo fehlschlägt. Interessant ist auch, dass es 2018 zu einer ähnlichen Situation kam und Qualys-Forscher beim Versuch, einen Exploit für die Schwachstelle CVE-2018-14634 im Linux-Kernel zu schreiben, auf drei kritische Schwachstellen in systemd stießen.

Source: opennet.ru

Kommentar hinzufügen