
Analyse technique approfondie et scanner pour CVE-2026-24061, un contournement d'authentification critique dans GNU InetUtils telnetd, incluant la chaîne d'exploitation, le PoC et les détails du correctif.
CVE-2026-24061 est une vulnérabilité critique (CVSS 9.8) de contournement d'authentification à distance dans GNU InetUtils telnetd qui permet à des attaquants non authentifiés d'obtenir un accès root instantané. La vulnérabilité provient d'une mauvaise assainissement de la variable d'environnement USER, qui est transmise directement à /usr/bin/login comme argument de ligne de commande. En définissant USER=-f root, un attaquant déclenche le drapeau -f de login, qui contourne entièrement l'authentification.
Versions affectées : GNU InetUtils 1.9.3 à 2.7 Type de vulnérabilité : CWE-88 (Injection d'arguments) Date de découverte : 20 janvier 2026 Découvreur : Kyu Neushwaistein (alias Carlos Cortes Alvarez)
telnetd/telnetd.c, lignes ~49-63)La vulnérabilité commence par une chaîne de modèle de commande qui définit comment telnetd invoque /usr/bin/login :
/* Template command line for invoking login program. */
char *login_invocation =
#ifdef SOLARIS10
PATH_LOGIN " -p -h %h %?T{-t %T} -d %L %?u{-u %u}{%U}"
#elif defined SOLARIS
PATH_LOGIN " -h %h %?T{%T} %?u{-- %u}{%U}"
#else /* !SOLARIS */
PATH_LOGIN " -p -h %h %?u{-f %u}{%U}"
#endif
;
Observation clé : Sur les systèmes non-Solaris, le modèle utilise :
%?u{-f %u}{%U} - C'est une expression conditionnelle signifiant :
user_name est défini (%u), utiliser -f %u (connexion automatique authentifiée)%U (la variable d'environnement USER comme solution de repli)Le problème critique : %U se développe en la variable d'environnement USER brute et non assainie.
telnetd/utility.c, _var_short_name())La chaîne de modèle est traitée par expand_line(), qui appelle _var_short_name() pour développer les espaces réservés. Voici le code vulnérable :
/* Expand a variable referenced by its short one-symbol name. */
char *
_var_short_name (struct line_expander *exp)
{
char *q;
char timebuf[64];
time_t t;
switch (*exp->cp++)
{
case 'a':
#ifdef AUTHENTICATION
if (auth_level >= 0 && autologin == AUTH_VALID)
return xstrdup ("ok");
#endif
return NULL;
case 'd':
time (&t);
strftime (timebuf, sizeof (timebuf),
"%l:%M%p on %A, %d %B %Y", localtime (&t));
return xstrdup (timebuf);
case 'h':
return xstrdup (remote_hostname); // POTENTIELLEMENT VULNÉRABLE
case 'l':
return xstrdup (local_hostname);
case 'L':
return xstrdup (line);
case 't':
q = strchr (line + 1, '/');
if (q)
q++;
else
q = line;
return xstrdup (q);
case 'T':
return terminaltype ? xstrdup (terminaltype) : NULL; // POTENTIELLEMENT VULNÉRABLE
case 'u':
return user_name ? xstrdup (user_name) : NULL;
case 'U':
return getenv ("USER") ? xstrdup (getenv ("USER")) : xstrdup (""); // VULNÉRABLE !
default:
exp->state = EXP_STATE_ERROR;
return NULL;
}
}
Le bug critique (cas 'U') : La variable d'environnement USER est récupérée via getenv() et transmise sans aucun assainissement. Lorsqu'un attaquant définit USER=-f root, cela devient partie intégrante de la ligne de commande de login.
telnetd/pty.c, start_login())La chaîne d'invocation de login développée est exécutée dans start_login() :
/* Construct login command from template */
argcv_string (argcv_length (argv, NULL), argv, &login_cmd);
/* Execute login - this runs: /usr/bin/login -p -h <hostname> -f root */
execv (argv[0], argv);
L'attaquant se connecte à telnetd (port 23)
La négociation d'options Telnet se produit :
IAC DO NEW_ENVIRONIAC WILL NEW_ENVIRONIAC SB NEW_ENVIRON SEND (demande de l'environnement)IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SELe serveur traite la variable USER :
getenv("USER") retourne -f root%U se développe en -f root/usr/bin/login -p -h <hostname> -f rootLogin interprète -f root :
-f signifie « ignorer l'authentification, l'utilisateur est pré-authentifié »root est le nom d'utilisateur avec lequel se connecter# Sur la machine de l'attaquant :
USER='-f root' telnet -a <ip_cible>
Le drapeau -a active le mode de connexion automatique, qui envoie la variable d'environnement USER au serveur.
L'avis de sécurité note explicitement : « Il existe donc un potentiel de vulnérabilités similaires pour d'autres variables. » Analysons chaque variable dans _var_short_name() :
| Var | Nom | Source | Contrôlable par l'utilisateur ? | Assainie ? | Surface d'attaque |
|---|---|---|---|---|---|
%U | Variable env. USER | getenv("USER") | OUI (via NEW_ENVIRON) | NON | CRITIQUE - CVE-2026-24061 |
%h | remote_hostname | Recherche DNS/PTR | Partielle (enregistrement PTR) | NON | ÉLEVÉE |
%T | terminaltype | Option TERMINAL-TYPE | OUI | NON | MOYENNE |
%u | user_name | Négociation de protocole | OUI | NON | MOYENNE (nécessite une authentification) |
%l | local_hostname | Configuration système | NON | N/A | FAIBLE |
%L | line (TTY) | Alloué par le système | NON | N/A | FAIBLE |
%t | nom court tty | Alloué par le système | NON | N/A | FAIBLE |
%d | date/heure | Horloge système | NON | N/A | AUCUNE |
%a | statut d'authentification | État interne | NON | N/A | AUCUNE |
%h - Nom d'hôte distant (RISQUE ÉLEVÉ)Source : Rempli dans telnetd_setup() depuis telnetd.c via getnameinfo() ou gethostbyaddr().
Le problème : Si un attaquant contrôle son enregistrement PTR (DNS inverse), il pourrait potentiellement injecter :
foo -f root
Comme nom d'hôte, qui deviendrait partie intégrante de l'argument -h :
/usr/bin/login -p -h "foo -f root" ...
Difficulté d'exploitation :
Scénario réel : Un attaquant contrôlant l'enregistrement PTR de son IP (courant pour les fournisseurs VPS) pourrait définir son DNS inverse à une valeur malveillante.
%T - Type de terminal (RISQUE MOYEN)Source : Reçu via la sous-négociation Telnet TERMINAL-TYPE, stocké dans la variable terminaltype.
Le problème : La chaîne de type de terminal est contrôlée par l'attaquant et non assainie :
case 'T':
return terminaltype ? xstrdup (terminaltype) : NULL;
Utilisation dans les modèles :
%?T{-t %T} - Utilisé avec le drapeau -t%?T{%T} - Inséré directementAttaque potentielle :
TERMINAL-TYPE: xterm -f root
Cependant, l'exploitation dépend de :
%T (actuellement uniquement Solaris)-t%u - Nom d'utilisateur authentifié (RISQUE MOYEN)Source : Défini pendant la négociation d'authentification.
Le problème : Utilisé dans le modèle -f %u :
PATH_LOGIN " -p -h %h %?u{-f %u}{%U}"
Si un attaquant pouvait manipuler user_name pour inclure des métacaractères shell ou des arguments supplémentaires, il pourrait obtenir une élévation de privilèges. Cependant, cette variable n'est généralement définie qu'après une certaine validation d'authentification.
%l, %L, %t : Ces valeurs dérivent de valeurs contrôlées par le système (nom d'hôte local, noms de périphériques TTY) que les attaquants ne peuvent pas influencer à distance.
%d : Généré à partir de l'horloge système - aucun vecteur d'injection.
%a : Variable d'état d'authentification interne - retourne littéralement « ok » ou NULL.
Sur la base de cette vulnérabilité, voici les modèles à rechercher dans la base de code :
// DANGEREUX : Utilisation directe de variables d'environnement
getenv("VARIABLE")
Fichiers à vérifier :
telnetd/utility.c - Autres fonctions d'expansiontelnetd/telnetd.c - Gestion de l'environnementrlogind/, rshd/ - Services similaires// DANGEREUX : Données utilisateur dans les modèles de commandes
sprintf(cmd, "commande %s", variable_controlee_utilisateur);
system(cmd);
execv(argv[0], argv);
// POTENTIELLEMENT DANGEREUX : Les données DNS peuvent être contrôlées par l'attaquant
getnameinfo(...); // Recherches PTR
gethostbyaddr(...);
// Puis utilisation du résultat dans la construction de commandes
Démon ftpd : Vérifier comment les entrées utilisateur sont gérées dans l'authentification et le traitement des commandes
Démons rshd/rlogind : Ceux-ci utilisent des modèles d'authentification similaires et peuvent avoir des problèmes comparables avec la gestion du nom d'hôte ou de l'environnement
Analyse de la configuration inetd : Peut traiter des entrées non fiables lors de la configuration des services
Points d'intégration Kerberos : Lors du traitement des noms de principaux ou des jetons d'authentification
fd702c02)Le premier correctif ajoute un assainissement de base :
case 'U':
{
char *u = getenv("USER");
return (u && *u != '-') ? xstrdup(u) : xstrdup("");
}
Cela bloque les valeurs commençant par -, ce qui empêche l'injection de drapeaux.
ccba9f74)Le deuxième correctif introduit une fonction sanitize() réutilisable pour toutes les entrées contrôlées par l'utilisateur :
/* Sanitize user-supplied string to prevent argument injection */
static char *
sanitize (const char *str)
{
if (str == NULL || *str == '-')
return xstrdup ("");
return xstrdup (str);
}
Appliquée à toutes les variables potentiellement dangereuses :
%U (USER)%h (remote_hostname)%T (terminaltype)CVE-2026-24061 est une vulnérabilité d'injection d'arguments classique qui est restée non détectée pendant 11 ans en raison de :
Des vulnérabilités similaires peuvent exister dans les variables %h (nom d'hôte) et %T (type de terminal), bien que l'exploitation soit plus complexe.
Implications plus larges : Tout code qui construit des commandes shell ou des arguments de programme à partir de données dérivées du réseau devrait être audité pour des vulnérabilités d'injection similaires.
Atténuations recommandées :
-f