Zum Inhalt springen

PersistenzAnti-Forensik

/etc/ld.so.preload und LD_PRELOAD: Linker-Hijacking

Preload-Datei des dynamischen Linkers, LD_PRELOAD und ld.so.conf: wie Userland-Rootkits Bibliotheken in jeden Prozess einschleusen und wie man sie erkennt.

Speicherort
/etc/ld.so.preload
Belegt
Ob eine Shared Library in dynamisch gelinkte Prozesse erzwungen wurde, welche und seit wann
Zeitstempel
mtime/ctime/crtime der Preload-Datei und der Bibliothek; keine internen Zeitstempel
Zugriff
root zum Schreiben; für alle lesbar; kann vom Rootkit selbst vor Live-Werkzeugen verborgen werden
Aufbewahrung
Bis zur Löschung; LD_PRELOAD in Prozessumgebungen besteht, bis der Prozess endet
Sicherung
UAC, debugfs, cp -a, AVML

Was es ist

Jedes dynamisch gelinkte Linux-Programm startet mit dem dynamischen Linker (ld.so / ld-linux*.so), der die benötigten Shared Libraries lädt. Davor lädt er alle Bibliotheken aus der Umgebungsvariablen LD_PRELOAD und anschließend die in /etc/ld.so.preload aufgeführten. Eine vorab geladene Bibliothek kann libc-Funktionen wie readdir, fopen oder execve überschreiben, und genau so verbergen Userland-Rootkits Dateien, Prozesse und Netzwerkverbindungen (MITRE ATT&CK T1574.006). MITRE nennt Hildegard und Rocke unter den Familien, die /etc/ld.so.preload verändert haben.

Die verwandten Dateien /etc/ld.so.conf, /etc/ld.so.conf.d/*.conf und /etc/ld.so.cache steuern, wo nach Bibliotheken gesucht wird. Sie wirken weniger direkt, lassen sich aber missbrauchen, damit eine bösartige Kopie einer Bibliothek bei der Suche gewinnt.

Wo es liegt

ArtefaktPfadNormalzustand
Systemweite Preload-Liste/etc/ld.so.preloadFehlt auf gängigen Installationen von Debian, Ubuntu und der RHEL-Familie
Preload pro ProzessLD_PRELOAD in /proc/<pid>/environNormalerweise nicht gesetzt
Wo es gesetzt wird/etc/environment, Shell-Startdateien, systemd Environment=, ~/.ssh/environmentEnthält selten LD_PRELOAD
Konfiguration der Bibliothekssuche/etc/ld.so.conf (meist include /etc/ld.so.conf.d/*.conf), /etc/ld.so.conf.d/*.confNur Einträge aus Paketen
Kompilierter Cache/etc/ld.so.cacheVon ldconfig neu erzeugt
Geladene Bibliotheken (live)/proc/<pid>/mapsNur erwartete Bibliotheken

Die Pfade sind in allen Distributionsfamilien gleich; die Bibliotheksverzeichnisse unterscheiden sich (/usr/lib/x86_64-linux-gnu unter Debian/Ubuntu, /usr/lib64 unter RHEL/Fedora).

Was es belegt

  • Eine in /etc/ld.so.preload aufgeführte Bibliothek wurde in jedes dynamisch gelinkte Programm geladen, das nach dem Anlegen der Datei gestartet wurde, einschließlich sshd-Sitzungen und root-Shells.
  • LD_PRELOAD in einer Prozessumgebung zeigt, dass dieser Prozess und in der Regel seine Kindprozesse mit der eingeschleusten Bibliothek liefen.
  • Die Funktionen der Bibliothek bestimmen die Reichweite des Rootkits: Hooks auf Verzeichnisauflistungen bedeuten versteckte Dateien, Hooks auf Authentifizierungsfunktionen deuten auf das Abgreifen von Zugangsdaten.
  • Nicht belegt: Statisch gelinkte Programme nutzen den dynamischen Linker nicht und sind nicht betroffen. Das bloße Vorhandensein der Datei verrät nicht, was die Bibliothek tut; dafür ist Reverse Engineering nötig.

Wichtige Felder

ElementBedeutung
Inhalt von /etc/ld.so.preloadDurch Leerraum getrennte Liste von Pfaden zu Shared Objects
LadereihenfolgeZuerst LD_PRELOAD, dann die Option --preload von ld.so, dann /etc/ld.so.preload
Secure-Execution-ModusBei setuid-/setgid- oder Capability-Programmen (AT_SECURE) werden LD_PRELOAD-Einträge mit Schrägstrich ignoriert, und nur setuid-Bibliotheken in Standardverzeichnissen werden geladen
LD_LIBRARY_PATH, LD_AUDITWeitere Linker-Variablen, die auf dieselbe Weise missbraucht werden; im Secure-Execution-Modus eingeschränkt (LD_LIBRARY_PATH wird ignoriert; LD_AUDIT lädt wie LD_PRELOAD nur Set-User-ID-Bibliotheken aus Standardverzeichnissen)
/etc/ld.so.conf.d/*.confEin Verzeichnis pro Zeile; ein vom Angreifer früh eingetragenes Verzeichnis kann echte Bibliotheken überdecken

Zeitstempel

Es gibt keine internen Zeitstempel. Nutzen Sie mtime, ctime und Erstellungszeit von /etc/ld.so.preload, der darin genannten Bibliothek und von /etc/ld.so.cache (wird bei jedem Lauf von ldconfig neu geschrieben). Die Erstellungszeit der Preload-Datei ist meist die beste Schätzung dafür, wann das Hooking begann. Vergleichen Sie mit den Startzeiten der Prozesse (siehe /proc-Live-Artefakte): Früher gestartete Prozesse tragen die Bibliothek nicht, sofern sie nicht neu gestartet wurden.

Aufbewahrung

Die Datei bleibt bis zur Löschung bestehen. Ihr Entfernen entlädt die Bibliothek nicht aus bereits laufenden Prozessen. In einer Prozessumgebung gesetztes LD_PRELOAD verschwindet, wenn der Prozess endet; sichern Sie es also live oder aus dem Arbeitsspeicher.

Sicherung

Ein Preload-Rootkit kann seine eigene Konfiguration vor Werkzeugen verbergen, die libc nutzen. Lesen Sie die Datei deshalb unterhalb der libc-Schicht:

  • Aus einem Datenträger-Image oder einem schreibgeschützten Mount auf einem sauberen Analysesystem (bevorzugt).
  • Auf einem laufenden Host mit einem statisch gelinkten Werkzeug oder direkt aus dem Dateisystem: UAC enthält ein Artefakt, das /etc/ld.so.preload auf ext-Dateisystemen mit debugfs bzw. auf XFS mit xfs_db ausliest und die stat-Daten auch dann festhält, wenn die Datei versteckt ist.
  • Sichern Sie den Arbeitsspeicher (AVML oder LiME), damit sich vorab geladene Bibliotheken pro Prozess extrahieren lassen.
# live, ext4 root on /dev/sda1: read the file through debugfs rather than libc
debugfs -R 'cat /etc/ld.so.preload' /dev/sda1
debugfs -R 'stat /etc/ld.so.preload' /dev/sda1
# live, static busybox from trusted media
/media/ir/busybox cat /etc/ld.so.preload
/media/ir/busybox grep -l LD_PRELOAD /proc/[0-9]*/environ

Auswertung

R=/mnt/evidence
ls -la --time-style=full-iso "$R"/etc/ld.so.preload && cat "$R"/etc/ld.so.preload
grep -rn 'LD_PRELOAD\|LD_LIBRARY_PATH\|LD_AUDIT' "$R"/etc "$R"/root "$R"/home/*/.[a-z]* 2>/dev/null
cat "$R"/etc/ld.so.conf "$R"/etc/ld.so.conf.d/*.conf
ldconfig -p -C "$R"/etc/ld.so.cache | less     # cache contents from the image

Im Arbeitsspeicher zeigt Volatility 3 mit linux.envars das LD_PRELOAD pro Prozess, linux.proc.Maps listet eingeblendete Bibliotheken auf, und linux.elfs kann sie zur Analyse extrahieren. Velociraptors Linux.Sys.Maps bietet dieselbe Sicht über eine ganze Flotte laufender Systeme.

Tipps für die Untersuchung

  • Behandeln Sie jede /etc/ld.so.preload auf einem Server als vorrangigen Befund, bis sie erklärt ist. Soll ein Produkt sie benötigen, prüfen Sie die Paketzugehörigkeit der Bibliothek mit dpkg -S oder rpm -qf und die Herstellerdokumentation.
  • Zeigt ls /etc auf dem laufenden Host die Datei nicht, ein statisches Werkzeug oder debugfs dagegen schon, haben Sie einen starken Beleg für ein aktives Rootkit.
  • Derselbe Bibliothekspfad in /proc/<pid>/maps vieler unzusammenhängender Prozesse ist die Live-Signatur eines systemweiten Preloads.
  • Bösartige Bibliotheken tragen oft Namen, die zwischen Systembibliotheken nicht auffallen; prüfen Sie Dateityp, Eigentümer, ctime und ob ein Paket sie ausliefert.
  • ldd kann ein nicht vertrauenswürdiges Programm ausführen; untersuchen Sie es stattdessen mit readelf -d oder objdump -p.
  • Suchen Sie das Ereignis des Einbringens: Eine neue /etc/ld.so.preload kurz vor einem Neustart von sshd oder anderen Daemons ist ein Muster aus realen Fällen. Prüfen Sie systemd-Units und das Journal auf diesen Neustart.
  • Preload-Rootkits können sich nicht vor dem Kernel verstecken; widersprechen sich Userland- und Speicheranalyse, vertrauen Sie dem Speicher. Wirkt beides sauber, das Verhalten aber auffällig, sehen Sie sich die Kernel-Module an.

Siehe auch