[Bug Report] GNU inetutils telnetd Local Privilege Escalation

"Labs, STAR" <[email protected]> Wed, 4 Mar 2026 10:12:07 +0800
Newsgroups gmane.comp.gnu.inetutils.bugs
Message-ID <CADbgxtzGe0cBX9ar9XM4m8d1TWCiSfi3-7F8pYed7VvfFK9MMg@mail.gmail.com>
--00000000000074e85e064c295983
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Hi,

our team member, Shi Weiming, would like to report the following bug in GNU
inetutils telnetd.

# GNU inetutils telnetd Local Privilege Escalation via GCONV_PATH
Environment Variable Injection

## Summary

| Field | Value |
|-------|-------|
| Vulnerability Type | CWE-269: Improper Privilege Management |
| Affected Software | GNU inetutils telnetd =E2=89=A4 2.7 |
| Severity | High (CVSS 3.1: 7.8) |
| Attack Vector | Local (requires valid local account + telnetd running) |
| Impact | Local Privilege Escalation to root |
| Related CVE | CVE-2026-28372 (CREDENTIALS_DIRECTORY vector, same root
cause) |
| Related CVE | CVE-2026-24061 (Remote auth bypass via USER, same root
cause) |
| Fix Status | **Unpatched** as of inetutils 2.7 (latest release,
2025-12-14) |

**Note:** CVE-2026-28372 officially describes only the
CREDENTIALS_DIRECTORY attack vector. The GCONV_PATH exploitation path
documented in this report shares the same root cause (incomplete
`scrub_env()` blacklist) but represents a **distinct and independently
exploitable attack vector** that has not been assigned a separate CVE as of
this writing. Unlike the CREDENTIALS_DIRECTORY vector which requires
util-linux =E2=89=A5 2.40 login, the GCONV_PATH vector works against **any*=
* login
implementation on any glibc-based system.

## Affected Versions

| Distribution | Package Version | Upstream Version | Status |
|---|---|---|---|
| GNU inetutils upstream | - | =E2=89=A4 2.7 | Vulnerable |
| Debian sid (unstable) | 2:2.7-3 | 2.7 | **Confirmed Exploitable** |
| Debian bullseye (11) | 2:2.0-1+deb11u3 | 2.0 | **Confirmed Exploitable** =
|
| Debian bookworm (12) | 2:2.4-2+deb12u2 | 2.4 | Vulnerable |
| Debian trixie (13) | 2:2.6-3+deb13u1 | 2.6 | Vulnerable |
| Ubuntu 24.04 | 2:2.5-3ubuntu4 | 2.5 | Vulnerable |
| Ubuntu 24.10 | 2:2.5-5ubuntu1 | 2.5 | Vulnerable |

## Comparison with CVE-2026-28372 (CREDENTIALS_DIRECTORY)

| Aspect | CVE-2026-28372 (CREDENTIALS_DIRECTORY) | This Report
(GCONV_PATH) |
|--------|----------------------------------------|------------------------=
--|
| Root Cause | scrub_env() blacklist incomplete | scrub_env() blacklist
incomplete |
| Injected Variables | CREDENTIALS_DIRECTORY | GCONV_PATH, OUTPUT_CHARSET,
LANG, LANGUAGE |
| Prerequisite | util-linux login =E2=89=A5 2.40 (systemd credential suppor=
t) | Any
glibc-based login (no version restriction) |
| Trigger Mechanism | login reads login.noauth from CREDENTIALS_DIRECTORY |
gettext =E2=86=92 iconv_open =E2=86=92 dlopen(evil.so) |
| Applicable Systems | Only systems with util-linux =E2=89=A5 2.40 | **All
glibc-based Linux systems** |
| CVE Assigned | Yes (CVE-2026-28372) | **No** |

**The GCONV_PATH vector has a broader attack surface** because it does not
depend on a specific version of util-linux login =E2=80=94 it exploits glib=
c's
iconv mechanism which is universally present on Linux systems.

## Vulnerability Description

GNU inetutils telnetd contains a local privilege escalation vulnerability
caused by an insufficient environment variable blacklist in its
`scrub_env()` function. The Telnet protocol's NEW-ENVIRON option (RFC 1572)
allows clients to set arbitrary environment variables on the server side.
Before executing `/bin/login`, telnetd attempts to sanitize the environment
by removing dangerous variables, but the blacklist only covers:

- `LD_*` (Linux dynamic linker)
- `_RLD_*` (IRIX dynamic linker)
- `LIBPATH` (AIX shared library path)
- `IFS` (shell field separator)

This blacklist, dating back to David Borman's 1995 telnet security fix,
fails to filter modern glibc-sensitive variables including `GCONV_PATH`,
`OUTPUT_CHARSET`, `LANG`, and `LANGUAGE`.

Since telnetd runs as root and executes `/bin/login` as root (a
root-to-root transition), the Linux kernel does not set `AT_SECURE=3D1`.
Without `AT_SECURE`, glibc does not enter secure-execution mode and honors
`GCONV_PATH`, allowing an attacker to load arbitrary shared objects into
the login process.

## Root Cause Analysis

### scrub_env() =E2=80=94 Incomplete Blacklist

Source: `telnetd/pty.c` (GNU inetutils =E2=89=A4 2.7)

```c
static void
scrub_env (void)
{
  char **cpp, **cpp2;

  for (cpp2 =3D cpp =3D environ; *cpp; cpp++)
    {
      if (strncmp (*cpp, "LD_", 3)
          && strncmp (*cpp, "_RLD_", 5)
          && strncmp (*cpp, "LIBPATH=3D", 8)
          && strncmp (*cpp, "IFS=3D", 4))
        *cpp2++ =3D *cpp;
    }
  *cpp2 =3D 0;
}
```

Variables NOT filtered: `GCONV_PATH`, `OUTPUT_CHARSET`, `LANG`, `LANGUAGE`,
`GLIBC_TUNABLES`, `CREDENTIALS_DIRECTORY`, `BASH_ENV`, `ENV`, `PYTHONPATH`,
`PERL5LIB`, `RUBYLIB`, and 90+ others.

Our comprehensive testing injected 115 environment variables via
NEW-ENVIRON. **101 variables survived** into the login process. Only 14
were blocked (LD_*, _RLD_*, LIBPATH, IFS, and a few others filtered by
login itself like PATH, PS1).

### AT_SECURE=3D0 =E2=80=94 No glibc Secure Mode

The Linux kernel sets `AT_SECURE=3D1` in the auxiliary vector when:
- The real UID =E2=89=A0 effective UID (setuid programs)
- The real GID =E2=89=A0 effective GID (setgid programs)
- Process lacks capabilities that the new program gains

telnetd runs as root (uid=3D0) and executes login as root (uid=3D0). Since
there is no UID/GID transition, `AT_SECURE` remains 0. glibc's
secure-execution mode, which would normally ignore `GCONV_PATH`, is
therefore **not activated**.

### glibc iconv =E2=80=94 GCONV_PATH Module Loading

When `GCONV_PATH` is set and `AT_SECURE=3D0`, glibc's iconv implementation
searches the specified directory for `gconv-modules` files. If a requested
charset is not found in the system `gconv-modules.cache`, glibc falls back
to scanning `GCONV_PATH` directories, reads the `gconv-modules` file, and
`dlopen()`s the corresponding shared object.

## Exploitation Technique

This exploit adapts the technique from CVE-2021-4034 (PwnKit) to the
telnetd context.

### Attack Chain

```
Attacker's telnet client
    =E2=94=82
    =E2=94=82  Telnet NEW-ENVIRON option (RFC 1572)
    =E2=94=82  Injects: GCONV_PATH, OUTPUT_CHARSET, LANG, LANGUAGE
    =E2=96=BC
telnetd (running as root, pid=3DN)
    =E2=94=82
    =E2=94=82  scrub_env() =E2=80=94 does NOT filter GCONV_PATH
    =E2=94=82  execv("/bin/login", ...) =E2=80=94 root=E2=86=92root, AT_SEC=
URE=3D0
    =E2=96=BC
/bin/login (running as root, pid=3DN)
    =E2=94=82
    =E2=94=82  gettext() =E2=86=92 detects LANG=3Dja_JP.eucjp, LANGUAGE=3Dj=
a
    =E2=94=82  Loads Japanese translation =E2=86=92 charset mismatch detect=
ed
    =E2=94=82  iconv_open("PWNKIT", "EUC-JP")
    =E2=94=82  "PWNKIT" not in gconv-modules.cache
    =E2=94=82  Searches GCONV_PATH=3D/home/attacker/.gconv_pwn/
    =E2=94=82  Reads gconv-modules =E2=86=92 maps PWNKIT to evil.so
    =E2=94=82  dlopen("evil.so") =E2=86=92 __attribute__((constructor)) run=
s as root
    =E2=96=BC
evil.so constructor (uid=3D0, euid=3D0)
    =E2=94=82
    =E2=94=82  Creates /tmp/rootbash (setuid root copy of /bin/bash)
    =E2=96=BC
Attacker runs: /tmp/rootbash -p =E2=86=92 euid=3D0 (root)
```

### Key Environment Variables

| Variable | Value | Purpose |
|----------|-------|---------|
| `GCONV_PATH` | `/home/attacker/.gconv_pwn` | Points glibc to attacker's
gconv-modules + evil.so |
| `OUTPUT_CHARSET` | `PWNKIT` | Fake charset name not in system gconv cache
|
| `LANG` | `ja_JP.eucjp` | Triggers Japanese locale with EUC-JP encoding |
| `LANGUAGE` | `ja` | Forces gettext to load Japanese translations,
requiring charset conversion |

### Why "PWNKIT" Charset?

The system's `gconv-modules.cache` contains mappings for all standard
charsets (UTF-8, ISO-8859-1, EUC-JP, etc.). If the attacker used a real
charset name, glibc would find it in the cache and use the system's
conversion module, never searching `GCONV_PATH`.

By using a non-existent charset name ("PWNKIT"), the cache lookup fails,
and glibc falls back to scanning `GCONV_PATH` directories for a
`gconv-modules` file that maps "PWNKIT" to a shared object.


### Tested Versions

| Version | Result |
|---------|--------|
| inetutils 2.0 (Debian bullseye) | **uid=3D0 euid=3D0 =E2=80=94 Exploited*=
* |
| inetutils 2.7 (Debian sid, latest) | **uid=3D0 euid=3D0 =E2=80=94 Exploit=
ed** |

## Impact

An unprivileged local user with a valid account on a system running GNU
inetutils telnetd can escalate privileges to root by:

1. Preparing a malicious gconv shared object in their home directory (no
special permissions needed)
2. Connecting to the local telnetd via the telnet protocol
3. Injecting `GCONV_PATH` and charset-related environment variables via the
NEW-ENVIRON option
4. Logging in normally =E2=80=94 the login process loads the malicious .so =
as root

**No password for the root account is needed.** The attacker only needs
their own valid credentials. The exploit is reliable, deterministic, and
works regardless of which login implementation (shadow-utils, util-linux)
is used.

Unlike CVE-2026-28372's CREDENTIALS_DIRECTORY vector (which requires
util-linux =E2=89=A5 2.40), the GCONV_PATH vector exploits a fundamental gl=
ibc
mechanism present on virtually all Linux systems.

## Remediation

### Current Upstream Status (Unpatched)

As of GNU inetutils 2.7 (latest release, 2025-12-14), `GCONV_PATH` is **not
filtered** by `scrub_env()`. The only post-disclosure change is an
`unsetenv("CREDENTIALS_DIRECTORY")` call added to `start_login()` on
2026-02-15, which addresses CVE-2026-28372 but does **not** mitigate the
GCONV_PATH vector.

The `scrub_env()` function still uses the original blacklist approach from
1995. No whitelist-based fix has been committed or released.

### Recommended Fix

Replace the blacklist in `scrub_env()` with a whitelist that only preserves
known-safe variables (e.g., `TERM`, `DISPLAY`, `USER`, `LOGNAME`,
`POSIXLY_CORRECT`). This is the approach recommended by Solar Designer on
the oss-security mailing list.

### Workarounds

1. **Disable telnetd**: Stop and disable the telnetd service. Use SSH
instead.
2. **Network isolation**: Restrict telnetd access to trusted networks via
firewall rules.
3. **Manual patch**: Add `GCONV_PATH`, `GCONV_MODULE_PATH`,
`OUTPUT_CHARSET`, `LANGUAGE`, `GLIBC_TUNABLES`, and other dangerous
variables to the `scrub_env()` blacklist (quick fix, but whitelist approach
is strongly preferred).

## Timeline

| Date | Event |
|------|-------|
| 2026-01-20 | telnetd vulnerabilities disclosed on oss-security mailing
list |
| 2026-01-26 | CISA adds CVE-2026-24061 (remote auth bypass) to KEV catalog
|
| 2026-02 | CVE-2026-28372 assigned (CREDENTIALS_DIRECTORY vector) |
| 2026-02-15 | Upstream adds unsetenv("CREDENTIALS_DIRECTORY") =E2=80=94 GC=
ONV_PATH
still unpatched |
| 2026-03-03 | This report: GCONV_PATH vector independently confirmed on
inetutils 2.0 and 2.7 |

## References

- [GNU inetutils official site](https://www.gnu.org/software/inetutils/)
- [GNU Savannah inetutils git =E2=80=94 telnetd/pty.c scrub_env()](
https://git.savannah.gnu.org/cgit/inetutils.git/tree/telnetd/pty.c)
- [NVD =E2=80=94 CVE-2026-28372](https://nvd.nist.gov/vuln/detail/CVE-2026-=
28372)
- [NVD =E2=80=94 CVE-2026-24061](https://nvd.nist.gov/vuln/detail/CVE-2026-=
24061)
- [oss-security: Series of new vulnerabilities in telnetd](
https://www.openwall.com/lists/oss-security/2026/01/20/2)
- [CVE-2021-4034 (PwnKit) =E2=80=94 Original GCONV_PATH exploitation techni=
que](
https://blog.qualys.com/vulnerabilities-threat-research/2022/01/25/pwnkit-l=
ocal-privilege-escalation-vulnerability-discovered-in-polkits-pkexec-cve-20=
21-4034
)
- [RFC 1572 =E2=80=94 Telnet Environment Option](https://tools.ietf.org/htm=
l/rfc1572
)
- [glibc iconv / gconv internals](https://sourceware.org/glibc/wiki/Gconv)

--00000000000074e85e064c295983
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr">Hi,<div><br></div><div>our team member, S=
hi Weiming, would like to report the following bug in=C2=A0GNU inetutils te=
lnetd.</div><div><br></div><div># GNU inetutils telnetd Local Privilege Esc=
alation via GCONV_PATH Environment Variable Injection<br><br>## Summary<br>=
<br>| Field | Value |<br>|-------|-------|<br>| Vulnerability Type | CWE-26=
9: Improper Privilege Management |<br>| Affected Software | GNU inetutils t=
elnetd =E2=89=A4 2.7 |<br>| Severity | High (CVSS 3.1: 7.8) |<br>| Attack V=
ector | Local (requires valid local account + telnetd running) |<br>| Impac=
t | Local Privilege Escalation to root |<br>| Related CVE | CVE-2026-28372 =
(CREDENTIALS_DIRECTORY vector, same root cause) |<br>| Related CVE | CVE-20=
26-24061 (Remote auth bypass via USER, same root cause) |<br>| Fix Status |=
 **Unpatched** as of inetutils 2.7 (latest release, 2025-12-14) |<br><br>**=
Note:** CVE-2026-28372 officially describes only the CREDENTIALS_DIRECTORY =
attack vector. The GCONV_PATH exploitation path documented in this report s=
hares the same root cause (incomplete `scrub_env()` blacklist) but represen=
ts a **distinct and independently exploitable attack vector** that has not =
been assigned a separate CVE as of this writing. Unlike the CREDENTIALS_DIR=
ECTORY vector which requires util-linux =E2=89=A5 2.40 login, the GCONV_PAT=
H vector works against **any** login implementation on any glibc-based syst=
em.<br><br>## Affected Versions<br><br>| Distribution | Package Version | U=
pstream Version | Status |<br>|---|---|---|---|<br>| GNU inetutils upstream=
 | - | =E2=89=A4 2.7 | Vulnerable |<br>| Debian sid (unstable) | 2:2.7-3 | =
2.7 | **Confirmed Exploitable** |<br>| Debian bullseye (11) | 2:2.0-1+deb11=
u3 | 2.0 | **Confirmed Exploitable** |<br>| Debian bookworm (12) | 2:2.4-2+=
deb12u2 | 2.4 | Vulnerable |<br>| Debian trixie (13) | 2:2.6-3+deb13u1 | 2.=
6 | Vulnerable |<br>| Ubuntu 24.04 | 2:2.5-3ubuntu4 | 2.5 | Vulnerable |<br=
>| Ubuntu 24.10 | 2:2.5-5ubuntu1 | 2.5 | Vulnerable |<br><br>## Comparison =
with CVE-2026-28372 (CREDENTIALS_DIRECTORY)<br><br>| Aspect | CVE-2026-2837=
2 (CREDENTIALS_DIRECTORY) | This Report (GCONV_PATH) |<br>|--------|-------=
---------------------------------|--------------------------|<br>| Root Cau=
se | scrub_env() blacklist incomplete | scrub_env() blacklist incomplete |<=
br>| Injected Variables | CREDENTIALS_DIRECTORY | GCONV_PATH, OUTPUT_CHARSE=
T, LANG, LANGUAGE |<br>| Prerequisite | util-linux login =E2=89=A5 2.40 (sy=
stemd credential support) | Any glibc-based login (no version restriction) =
|<br>| Trigger Mechanism | login reads login.noauth from CREDENTIALS_DIRECT=
ORY | gettext =E2=86=92 iconv_open =E2=86=92 dlopen(evil.so) |<br>| Applica=
ble Systems | Only systems with util-linux =E2=89=A5 2.40 | **All glibc-bas=
ed Linux systems** |<br>| CVE Assigned | Yes (CVE-2026-28372) | **No** |<br=
><br>**The GCONV_PATH vector has a broader attack surface** because it does=
 not depend on a specific version of util-linux login =E2=80=94 it exploits=
 glibc&#39;s iconv mechanism which is universally present on Linux systems.=
<br><br>## Vulnerability Description<br><br>GNU inetutils telnetd contains =
a local privilege escalation vulnerability caused by an insufficient enviro=
nment variable blacklist in its `scrub_env()` function. The Telnet protocol=
&#39;s NEW-ENVIRON option (RFC 1572) allows clients to set arbitrary enviro=
nment variables on the server side. Before executing `/bin/login`, telnetd =
attempts to sanitize the environment by removing dangerous variables, but t=
he blacklist only covers:<br><br>- `LD_*` (Linux dynamic linker)<br>- `_RLD=
_*` (IRIX dynamic linker)<br>- `LIBPATH` (AIX shared library path)<br>- `IF=
S` (shell field separator)<br><br>This blacklist, dating back to David Borm=
an&#39;s 1995 telnet security fix, fails to filter modern glibc-sensitive v=
ariables including `GCONV_PATH`, `OUTPUT_CHARSET`, `LANG`, and `LANGUAGE`.<=
br><br>Since telnetd runs as root and executes `/bin/login` as root (a root=
-to-root transition), the Linux kernel does not set `AT_SECURE=3D1`. Withou=
t `AT_SECURE`, glibc does not enter secure-execution mode and honors `GCONV=
_PATH`, allowing an attacker to load arbitrary shared objects into the logi=
n process.<br><br>## Root Cause Analysis<br><br>### scrub_env() =E2=80=94 I=
ncomplete Blacklist<br><br>Source: `telnetd/pty.c` (GNU inetutils =E2=89=A4=
 2.7)<br><br>```c<br>static void<br>scrub_env (void)<br>{<br>=C2=A0 char **=
cpp, **cpp2;<br><br>=C2=A0 for (cpp2 =3D cpp =3D environ; *cpp; cpp++)<br>=
=C2=A0 =C2=A0 {<br>=C2=A0 =C2=A0 =C2=A0 if (strncmp (*cpp, &quot;LD_&quot;,=
 3)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &amp;&amp; strncmp (*cpp, &quot;_=
RLD_&quot;, 5)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &amp;&amp; strncmp (*c=
pp, &quot;LIBPATH=3D&quot;, 8)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &amp;&=
amp; strncmp (*cpp, &quot;IFS=3D&quot;, 4))<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
*cpp2++ =3D *cpp;<br>=C2=A0 =C2=A0 }<br>=C2=A0 *cpp2 =3D 0;<br>}<br>```<br>=
<br>Variables NOT filtered: `GCONV_PATH`, `OUTPUT_CHARSET`, `LANG`, `LANGUA=
GE`, `GLIBC_TUNABLES`, `CREDENTIALS_DIRECTORY`, `BASH_ENV`, `ENV`, `PYTHONP=
ATH`, `PERL5LIB`, `RUBYLIB`, and 90+ others.<br><br>Our comprehensive testi=
ng injected 115 environment variables via NEW-ENVIRON. **101 variables surv=
ived** into the login process. Only 14 were blocked (LD_*, _RLD_*, LIBPATH,=
 IFS, and a few others filtered by login itself like PATH, PS1).<br><br>###=
 AT_SECURE=3D0 =E2=80=94 No glibc Secure Mode<br><br>The Linux kernel sets =
`AT_SECURE=3D1` in the auxiliary vector when:<br>- The real UID =E2=89=A0 e=
ffective UID (setuid programs)<br>- The real GID =E2=89=A0 effective GID (s=
etgid programs)<br>- Process lacks capabilities that the new program gains<=
br><br>telnetd runs as root (uid=3D0) and executes login as root (uid=3D0).=
 Since there is no UID/GID transition, `AT_SECURE` remains 0. glibc&#39;s s=
ecure-execution mode, which would normally ignore `GCONV_PATH`, is therefor=
e **not activated**.<br><br>### glibc iconv =E2=80=94 GCONV_PATH Module Loa=
ding<br><br>When `GCONV_PATH` is set and `AT_SECURE=3D0`, glibc&#39;s iconv=
 implementation searches the specified directory for `gconv-modules` files.=
 If a requested charset is not found in the system `gconv-modules.cache`, g=
libc falls back to scanning `GCONV_PATH` directories, reads the `gconv-modu=
les` file, and `dlopen()`s the corresponding shared object.<br><br>## Explo=
itation Technique<br><br>This exploit adapts the technique from CVE-2021-40=
34 (PwnKit) to the telnetd context.<br><br>### Attack Chain<br><br>```<br>A=
ttacker&#39;s telnet client<br>=C2=A0 =C2=A0 =E2=94=82<br>=C2=A0 =C2=A0 =E2=
=94=82 =C2=A0Telnet NEW-ENVIRON option (RFC 1572)<br>=C2=A0 =C2=A0 =E2=94=
=82 =C2=A0Injects: GCONV_PATH, OUTPUT_CHARSET, LANG, LANGUAGE<br>=C2=A0 =C2=
=A0 =E2=96=BC<br>telnetd (running as root, pid=3DN)<br>=C2=A0 =C2=A0 =E2=94=
=82<br>=C2=A0 =C2=A0 =E2=94=82 =C2=A0scrub_env() =E2=80=94 does NOT filter =
GCONV_PATH<br>=C2=A0 =C2=A0 =E2=94=82 =C2=A0execv(&quot;/bin/login&quot;, .=
..) =E2=80=94 root=E2=86=92root, AT_SECURE=3D0<br>=C2=A0 =C2=A0 =E2=96=BC<b=
r>/bin/login (running as root, pid=3DN)<br>=C2=A0 =C2=A0 =E2=94=82<br>=C2=
=A0 =C2=A0 =E2=94=82 =C2=A0gettext() =E2=86=92 detects LANG=3Dja_JP.eucjp, =
LANGUAGE=3Dja<br>=C2=A0 =C2=A0 =E2=94=82 =C2=A0Loads Japanese translation =
=E2=86=92 charset mismatch detected<br>=C2=A0 =C2=A0 =E2=94=82 =C2=A0iconv_=
open(&quot;PWNKIT&quot;, &quot;EUC-JP&quot;)<br>=C2=A0 =C2=A0 =E2=94=82 =C2=
=A0&quot;PWNKIT&quot; not in gconv-modules.cache<br>=C2=A0 =C2=A0 =E2=94=82=
 =C2=A0Searches GCONV_PATH=3D/home/attacker/.gconv_pwn/<br>=C2=A0 =C2=A0 =
=E2=94=82 =C2=A0Reads gconv-modules =E2=86=92 maps PWNKIT to evil.so<br>=C2=
=A0 =C2=A0 =E2=94=82 =C2=A0dlopen(&quot;evil.so&quot;) =E2=86=92 __attribut=
e__((constructor)) runs as root<br>=C2=A0 =C2=A0 =E2=96=BC<br>evil.so const=
ructor (uid=3D0, euid=3D0)<br>=C2=A0 =C2=A0 =E2=94=82<br>=C2=A0 =C2=A0 =E2=
=94=82 =C2=A0Creates /tmp/rootbash (setuid root copy of /bin/bash)<br>=C2=
=A0 =C2=A0 =E2=96=BC<br>Attacker runs: /tmp/rootbash -p =E2=86=92 euid=3D0 =
(root)<br>```<br><br>### Key Environment Variables<br><br>| Variable | Valu=
e | Purpose |<br>|----------|-------|---------|<br>| `GCONV_PATH` | `/home/=
attacker/.gconv_pwn` | Points glibc to attacker&#39;s gconv-modules + evil.=
so |<br>| `OUTPUT_CHARSET` | `PWNKIT` | Fake charset name not in system gco=
nv cache |<br>| `LANG` | `ja_JP.eucjp` | Triggers Japanese locale with EUC-=
JP encoding |<br>| `LANGUAGE` | `ja` | Forces gettext to load Japanese tran=
slations, requiring charset conversion |<br><br>### Why &quot;PWNKIT&quot; =
Charset?<br><br>The system&#39;s `gconv-modules.cache` contains mappings fo=
r all standard charsets (UTF-8, ISO-8859-1, EUC-JP, etc.). If the attacker =
used a real charset name, glibc would find it in the cache and use the syst=
em&#39;s conversion module, never searching `GCONV_PATH`.<br><br>By using a=
 non-existent charset name (&quot;PWNKIT&quot;), the cache lookup fails, an=
d glibc falls back to scanning `GCONV_PATH` directories for a `gconv-module=
s` file that maps &quot;PWNKIT&quot; to a shared object.<br><br><br>### Tes=
ted Versions<br><br>| Version | Result |<br>|---------|--------|<br>| inetu=
tils 2.0 (Debian bullseye) | **uid=3D0 euid=3D0 =E2=80=94 Exploited** |<br>=
| inetutils 2.7 (Debian sid, latest) | **uid=3D0 euid=3D0 =E2=80=94 Exploit=
ed** |<br><br>## Impact<br><br>An unprivileged local user with a valid acco=
unt on a system running GNU inetutils telnetd can escalate privileges to ro=
ot by:<br><br>1. Preparing a malicious gconv shared object in their home di=
rectory (no special permissions needed)<br>2. Connecting to the local telne=
td via the telnet protocol<br>3. Injecting `GCONV_PATH` and charset-related=
 environment variables via the NEW-ENVIRON option<br>4. Logging in normally=
 =E2=80=94 the login process loads the malicious .so as root<br><br>**No pa=
ssword for the root account is needed.** The attacker only needs their own =
valid credentials. The exploit is reliable, deterministic, and works regard=
less of which login implementation (shadow-utils, util-linux) is used.<br><=
br>Unlike CVE-2026-28372&#39;s CREDENTIALS_DIRECTORY vector (which requires=
 util-linux =E2=89=A5 2.40), the GCONV_PATH vector exploits a fundamental g=
libc mechanism present on virtually all Linux systems.<br><br>## Remediatio=
n<br><br>### Current Upstream Status (Unpatched)<br><br>As of GNU inetutils=
 2.7 (latest release, 2025-12-14), `GCONV_PATH` is **not filtered** by `scr=
ub_env()`. The only post-disclosure change is an `unsetenv(&quot;CREDENTIAL=
S_DIRECTORY&quot;)` call added to `start_login()` on 2026-02-15, which addr=
esses CVE-2026-28372 but does **not** mitigate the GCONV_PATH vector.<br><b=
r>The `scrub_env()` function still uses the original blacklist approach fro=
m 1995. No whitelist-based fix has been committed or released.<br><br>### R=
ecommended Fix<br><br>Replace the blacklist in `scrub_env()` with a whiteli=
st that only preserves known-safe variables (e.g., `TERM`, `DISPLAY`, `USER=
`, `LOGNAME`, `POSIXLY_CORRECT`). This is the approach recommended by Solar=
 Designer on the oss-security mailing list.<br><br>### Workarounds<br><br>1=
. **Disable telnetd**: Stop and disable the telnetd service. Use SSH instea=
d.<br>2. **Network isolation**: Restrict telnetd access to trusted networks=
 via firewall rules.<br>3. **Manual patch**: Add `GCONV_PATH`, `GCONV_MODUL=
E_PATH`, `OUTPUT_CHARSET`, `LANGUAGE`, `GLIBC_TUNABLES`, and other dangerou=
s variables to the `scrub_env()` blacklist (quick fix, but whitelist approa=
ch is strongly preferred).<br><br>## Timeline<br><br>| Date | Event |<br>|-=
-----|-------|<br>| 2026-01-20 | telnetd vulnerabilities disclosed on oss-s=
ecurity mailing list |<br>| 2026-01-26 | CISA adds CVE-2026-24061 (remote a=
uth bypass) to KEV catalog |<br>| 2026-02 | CVE-2026-28372 assigned (CREDEN=
TIALS_DIRECTORY vector) |<br>| 2026-02-15 | Upstream adds unsetenv(&quot;CR=
EDENTIALS_DIRECTORY&quot;) =E2=80=94 GCONV_PATH still unpatched |<br>| 2026=
-03-03 | This report: GCONV_PATH vector independently confirmed on inetutil=
s 2.0 and 2.7 |<br><br>## References<br><br>- [GNU inetutils official site]=
(<a href=3D"https://www.gnu.org/software/inetutils/" target=3D"_blank">http=
s://www.gnu.org/software/inetutils/</a>)<br>- [GNU Savannah inetutils git =
=E2=80=94 telnetd/pty.c scrub_env()](<a href=3D"https://git.savannah.gnu.or=
g/cgit/inetutils.git/tree/telnetd/pty.c" target=3D"_blank">https://git.sava=
nnah.gnu.org/cgit/inetutils.git/tree/telnetd/pty.c</a>)<br>- [NVD =E2=80=94=
 CVE-2026-28372](<a href=3D"https://nvd.nist.gov/vuln/detail/CVE-2026-28372=
" target=3D"_blank">https://nvd.nist.gov/vuln/detail/CVE-2026-28372</a>)<br=
>- [NVD =E2=80=94 CVE-2026-24061](<a href=3D"https://nvd.nist.gov/vuln/deta=
il/CVE-2026-24061" target=3D"_blank">https://nvd.nist.gov/vuln/detail/CVE-2=
026-24061</a>)<br>- [oss-security: Series of new vulnerabilities in telnetd=
](<a href=3D"https://www.openwall.com/lists/oss-security/2026/01/20/2" targ=
et=3D"_blank">https://www.openwall.com/lists/oss-security/2026/01/20/2</a>)=
<br>- [CVE-2021-4034 (PwnKit) =E2=80=94 Original GCONV_PATH exploitation te=
chnique](<a href=3D"https://blog.qualys.com/vulnerabilities-threat-research=
/2022/01/25/pwnkit-local-privilege-escalation-vulnerability-discovered-in-p=
olkits-pkexec-cve-2021-4034" target=3D"_blank">https://blog.qualys.com/vuln=
erabilities-threat-research/2022/01/25/pwnkit-local-privilege-escalation-vu=
lnerability-discovered-in-polkits-pkexec-cve-2021-4034</a>)<br>- [RFC 1572 =
=E2=80=94 Telnet Environment Option](<a href=3D"https://tools.ietf.org/html=
/rfc1572" target=3D"_blank">https://tools.ietf.org/html/rfc1572</a>)<br>- [=
glibc iconv / gconv internals](<a href=3D"https://sourceware.org/glibc/wiki=
/Gconv" target=3D"_blank">https://sourceware.org/glibc/wiki/Gconv</a>)<br><=
/div></div>
</div>

--00000000000074e85e064c295983--