Hello, Do you have any updates regarding this subject?
Thank you, Ron On Tue, Feb 24, 2026 at 11:57 AM Ron Ben Yizhak < [email protected]> wrote: > Hi all, > > I’d like to ensure we follow the standard CVE process here. Standard > practice dictates that a CVE is issued per individual fix. Generally, once > a fix is merged and released, it is assigned its own CVE. Even if that fix > is later bypassed, the original merge stands as a unique event in the > codebase, meaning we should issue two separate CVEs rather than grouping > them. > > Justin - Thank you for emphasizing what I already noted previously in this > thread: > > "In my opinion the proposed fix will stop this exploit, but the main issue > stays. The issue exists as long as unauthenticated clients can set > arbitrary environment variables in the memory of telnetd and its sub > processes. > The best solution will be that the environment variables set by the client > will only apply on the shell process and only after the client has already > authenticated. No process running as root should run with any environment > variables set by the client." > > In spite of this opinion, it seems that the decision of the developers was > to first release something quick that will as least start by mitigating the > specific exploit that I shared, even though the main issue remains. I guess > that a concrete exploit that utilizes different environment variables might > change the prioritization for implementing an "AcceptEnv-like" logic in GNU > telnetd, but they might choose to just unset the environment variables that > you find as exploitable. > > Best regards, > Ron Ben Yizhak > > On Tue, Feb 24, 2026 at 3:16 AM Justin Swartz < > [email protected]> wrote: > >> Greetings, >> >> I have been reviewing the recent vulnerability report by Ron Ben Yizhak >> regarding CREDENTIALS_DIRECTORY, as well as commit 4db2f19f which >> introduces unsetenv("CREDENTIALS_DIRECTORY") to address the problem. >> >> After becoming aware of CVE-2026-24061 (telnetd in GNU Inetutils through >> 2.7 allows remote authentication bypass via a "-f root" value for the USER >> environment variable), I was curious to find out whether there'd also been >> a potential regression of CVE-1999-0073, described as: telnet allows a >> remote client to specify environment variables including LD_LIBRARY_PATH, >> allowing an attacker to bypass the normal system libraries and gain root >> access. I can confirm that this is still an issue 27 years later, despite >> attempts at blacklisting environment variables by prefix or full name. >> >> The problem stems from telnetd executing /bin/login in a root-to-root >> context, which means that AT_SECURE is set to 0 by the kernel in the >> process's auxiliary vector. When AT_SECURE holds a positive value, it >> informs the dynamic linker (ld-linux.so) and libc to enter a >> "secure-execution mode" where a bunch of interesting environment variables >> are discarded or, at least, defanged if present. In other words, the >> responsibility is on telnetd itself to ensure that none of those >> potentially interesting, and attacker controlled, variables make their way >> to /bin/login. >> >> While using unsetenv() negates a user's ability to exploit the >> login.noauth vector, the possibility still exists for the inclusion of >> variables of interest to GNU gettext (such as OUTPUT_CHARSET or LANGUAGE) >> and glibc (such as GCONV_PATH) via the telnet protocol itself. >> >> For example, by injecting OUTPUT_CHARSET and LANGUAGE, an attacker can >> persuade gettext that a character set conversion is necessary. This forces >> gettext to call libc's iconv_open(), and because AT_SECURE is 0, >> iconv_open() will use an injected GCONV_PATH in its quest for a >> gconv-modules file. Assuming the attacker already has a local unprivileged >> account, or at least a means of uploading files to the host (and knowing >> the location of the uploaded files), a custom gconv-modules file will allow >> arbitrary shared objects to be loaded soon after /bin/login attempts to >> print a localized prompt. >> >> For proof of concept, I've declared a broad selection of LANGUAGE codes >> for the best chance of matching an installed locale. An attacker with local >> access could simply determine what's actually installed and select only one >> that doesn't match the system's default locale instead. Similarly, >> OUTPUT_CHARSET has been chosen as a deliberate mismatch against the very >> common choice of UTF-8: >> >> [email protected]:~$ ls -al .gconv >> total 184 >> drwxr-xr-x 2 abuser abuser 4096 Jan 1 1970 . >> drwxr-x--- 5 abuser abuser 36864 Jan 1 1970 .. >> -rw-r--r-- 1 abuser abuser 256 Jan 1 1970 gconv-modules >> -rw-r--r-- 1 abuser abuser 15568 Jan 1 1970 libcash2trash.so >> >> >> [email protected]:~$ telnet -l abuser >> telnet> environ define GCONV_PATH /home/abuser/.gconv >> telnet> environ export GCONV_PATH >> telnet> environ define LANGUAGE >> fr:de:es:it:pt:nl:sv:pl:uk:ru:zh_CN:ko:ja >> telnet> environ export LANGUAGE >> telnet> environ define OUTPUT_CHARSET ISO-8859-1 >> telnet> environ export OUTPUT_CHARSET >> telnet> open 127.0.0.1 >> Trying 127.0.0.1... >> Connected to 127.0.0.1. >> Escape character is '^]'. >> >> Linux (localhost) (pts/6) >> >> Connection closed by foreign host. >> >> >> [email protected]:~$ ls -al .gconv >> total 184 >> drwxr-xr-x 2 abuser abuser 4096 Jan 1 1970 . >> drwxr-x--- 5 abuser abuser 36864 Jan 1 1970 .. >> -rw-r--r-- 1 abuser abuser 256 Jan 1 1970 gconv-modules >> -rw-r--r-- 1 abuser abuser 15568 Jan 1 1970 libcash2trash.so >> -rwsr-sr-x 1 root root 125640 Jan 1 1970 trash >> >> >> [email protected]:~$ .gconv/trash -p >> # id >> uid=1001(abuser) gid=1002(abuser) euid=0(root) egid=0(root) >> groups=0(root),1002(abuser) >> >> >> Once the telnet connection opens, /bin/login tries to print the localized >> prompt but gettext recognizes the encoding mismatch and calls iconv_open() >> to parse the gconv-modules file in the directory referenced by the injected >> path before loading the shared object that turns cash ($) to trash (#). The >> connection drops because I included a call to exit() once the payload has >> executed. As illustrated above, the payload effectively asserts root >> privilege and makes a copy of /bin/sh with SUID/SGID permissions. Note that >> no authentication via telnetd was required, nor performed, for this >> privilege escalation trick to occur. Also note that this is just one of >> many possible methods that may be used to exploit this condition. >> >> In my opinion, to fix this issue and finally put the ghost of >> CVE-1999-0073 to rest: telnetd must drop the blacklist approach and adopt >> the OpenSSH AcceptEnv-style approach suggested by Simon Josefsson [1], >> which amounts to preparing a brand new environment for /bin/login based on >> a strict whitelist of variables names considered to be "safe", and perhaps >> a healthy dose of input sanitization for their respective values. >> >> In terms of the CVE that Ron Ben Yizhak had asked about earlier in the >> thread: I think it might make the most sense to co-ordinate a single CVE >> for "Improper environment sanitization in telnetd" that comprehensively >> covers both the CREDENTIALS_DIRECTORY vector and this dynamic linker escape. >> >> I'm happy to share the intentionally redacted payload privately with the >> maintainers should any help be required to reproduce the proof of concept. >> >> Regards, >> Justin >> >> --- >> >> [1] >> https://lists.gnu.org/archive/html/bug-inetutils/2026-02/msg00002.html >> >
