Share
## https://sploitus.com/exploit?id=E8D3D809-C0D7-50FE-9708-4AA43EF9D6CA
# CVE-2026-24061 - telnetd auth bypass

## o co chodzi

argument injection w `telnetd` z GNU InetUtils. Wersje 1.9.3 do 2.7. CVSS 9.8. W CISA KEV od 26.01.2026, czyli aktywnie eksploitowane na wolnosci.

Caly trick polega na tym ze telnetd bierze wartosc zmiennej srodowiskowej `USER` od klienta przez NEW-ENVIRON (RFC 1572) i wkleja ja bez zadnej walidacji prosto do wywolania `login(1)`. Jesli klient wysle `USER="-f root"`, to telnetd uruchomi:

```
/usr/bin/login -p -h  -f root
```

Flaga `-f` w login oznacza "zaloguj tego usera bez hasla". Shell roota, zero uwierzytelniania.

## mechanizm

W `telnetd/telnetd.c` jest szablon wywolania login:

```c
char *login_invocation = PATH_LOGIN " -p -h %h %?u{-f %u}{%U}";
```

`%u` to user z autentykacji telnet (zaufany). `%U` to raw wartosc env `USER` od klienta (niezaufany). Kiedy autentykacja nie jest aktywna, uzywa sie `%U`.

Ekspansja zmiennych siedzi w `telnetd/utility.c`, funkcja `_var_short_name`:

```c
case 'U':
    return getenv("USER") ? xstrdup(getenv("USER")) : xstrdup("");
```

Zero filtrowania. Cokolwiek klient wysle w USER leci prosto do command line login. Nie tylko `-f root` dziala, teoretycznie kazdy argument ktory login akceptuje mozna wstrzyknac.

Bug wprowadzony w upsreamowym safe-guard commicie z 2015-03-19 (`fa3245ac`). Ironicznie, ten commit mial poprawic obsluge zmiennej USER. Debian mial patch na to w 2019 (`0028-telnetd-Scrub-USER-from-environment.patch`), ale przy fixie CVE-2020-10188 w Debian 10 patch sie zgubil i bug wrocil. Wiec podatne sa tez Debian 10+, Ubuntu i pochodne.

## jak dziala poc

`main.py` to minimalny klient telnet ktory:

1. laczy sie na port 23
2. w negocjacji akceptuje NEW-ENVIRON, reszta opcji WONT
3. na request SEND odpowiada `IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SE`
4. telnetd odpala `login -f root`, dostajesz shell
5. dalej dziala jak interaktywna sesja, filtruje IAC i ANSI escape z outputu

```
klient                                serwer
  |--- tcp connect ------------------->|
  ||
  ||
  |    [telnetd: login -p -h x -f root]|
  |
python3 main.py  -p 
```

Ctrl+C konczy sesje.

## co nie robic

Nie probuj tego na systemach ktore nie maja `inetutils-telnetd`. Pakiet `telnetd` z netkit to inny kod, nie jest podatny na ten konkretny bug. Jesli polaczysz sie i dostajesz normalny login prompt zamiast shella to albo serwer ma juz patch, albo to nie jest inetutils telnetd.

Nie zmieniaj payloadu na `-f ` oczekujac ze zadziala na kazdym systemie. login(1) z niektorych dystrybucji ma dodatkowe ograniczenia na `-f`. Na standardowym Debian/Ubuntu `-f root` dziala bez problemu.

## dotykane wersje

| soft | wersje |
|---|---|
| GNU InetUtils | 1.9.3 - 2.7 |
| Debian 10+ | inetutils-telnetd (do patcha) |
| Debian 11 | naprawione w 2:2.0-1+deb11u3 |
| Ubuntu | inetutils-telnetd (do patcha) |

## patch

Oficjalny fix dodaje funkcje `sanitize()` ktora odrzuca wartosci zaczynajace sie od `-` albo zawierajace shell metachars. Zastosowana do wszystkich zmiennych w ekspansji, nie tylko USER.

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

- `fd702c0` - patch USER
- `ccba9f7` - sanityzacja wszystkich zmiennych