
cPanel/WHM 인증 우회에 대한 기술 분석
방어자 관점의 기술 심층 분석
| 필드 | 값 |
|---|---|
| CVE ID | CVE-2026-41940 |
| CVSS v3.1 | 9.8 (치명적) — 네트워크 / 낮은 복잡도 / 권한 불요 / 사용자 상호작용 불요 |
| 취약점 분류 | 사전 인증 CRLF 인젝션 → 세션 파일 오염 → 인증 우회 |
| CWE | CWE-93 (CRLF 시퀀스의 부적절한 중화), 다만 주입된 CRLF가 HTTP 응답 헤더가 아닌 디스크 상의 세션 파일에 도달하므로 CWE-117 (로그/파일에 대한 부적절한 출력 중화)에 더 가깝다고 볼 수 있음 |
| 영향받는 제품 | cPanel, WHM (WebHost Manager), WP Squared |
| 영향 | 인증되지 않은 상태에서 WHM의 완전한 권한을 가진 루트 관리 세션을 원격으로 획득 |
| 공개일 | 2026년 4월 28일 (cPanel 보안 권고) |
| CVE 배정일 | 2026년 4월 29일 |
| 실제 공격 (in-the-wild) 발견 | 호스팅 제공업체 KnownHost에 따르면 2026년 2월 23일경부터 관찰됨 — 패치 배포보다 약 두 달 앞선 시점 |
| CISA KEV | 공개 직후 추가됨 |
| 추정 노출 규모 | 약 150만 개의 인터넷 노출 cPanel 인스턴스 (Rapid7이 인용한 Shodan 텔레메트리 기준); cPanel은 웹 제어판 시장의 약 94% 점유율 추정 (W3Techs) |
| 우회 방안 | 없음 — 패치만이 유일한 완전한 해결책 |
cPanel & WHM은 공유 및 리셀러 웹 호스팅에서 지배적인 제어판 소프트웨어입니다. cPanel은 고객 대상 계정 인터페이스이고, WHM은 호스팅 제공업체와 서버 소유자가 사용하는 루트 수준 관리 인터페이스입니다. 둘 다 동일한 Perl 데몬인 cpsrvd 가 제공하며, 각 표면에 대해 쌍을 이루는 포트(cPanel: 2082/2083, WHM: 2086/2087, Webmail: 2095/2096)에서 수신 대기합니다.
CVE-2026-41940은 어떤 자격 증명도 없이 공격자가 인증이 발생하기 전에 디스크 상의 세션 상태를 조작하여, 이후 cpsrvd가 공격자가 공급한 데이터를 정당한 완전 인증된 루트 권한 세션 속성으로 재해석하도록 만듭니다. 그 결과 해당 서버에 호스팅된 모든 웹사이트와 계정의 관리 평면이 완전히 장악됩니다. 이는 단일 테넌트 문제가 아니라 호스트 전체, 제공업체 전체, 그리고 집계적으로는 업계 전체의 문제입니다. cPanel의 시장 집중도를 고려할 때 더욱 그렇습니다.
9.8이라는 CVSS 점수는 흔해서 읽어도 무감각해질 수 있습니다. CVE-2026-41940이 실제로 비정상적으로 심각한 이유는 세 가지 구조적 요인 때문입니다:
폭발 반경(blast radius)이 계정이 아니라 서버 전체입니다. WHM 장악은 루트 권한 장악입니다. 해당 서버의 모든 고객 계정, 모든 데이터베이스, 모든 TLS 개인 키, 모든 백업, 모든 DNS 영역이 즉시 영향 범위에 들어옵니다.
약 두 달 동안 진정한 제로데이였습니다. KnownHost의 텔레메트리는 초기 악용 시점을 2026년 2월 23일경으로 추정하며, 이는 4월 28일 패치보다 훨씬 앞선 시점입니다. 해당 기간 동안 인터넷에 노출되어 있었던 조직은 공격 가능성을 단순한 이론이 아니라 실재하는 위협으로 가정하고, "우리는 패치했으니 괜찮다"는 태도 대신 사후 침해 평가(retrospective compromise assessment)를 수행해야 합니다.
대부분의 피해 조직은 스스로 패치할 수 없습니다. cPanel은 일반적으로 호스팅 제공업체가 테넌트를 대신하여 배포합니다. 최종 고객은 수정 사항에 대한 코드 수준의 통제권이 없으며 전적으로 제공업체의 패치 속도에 의존합니다. 이것이 바로 여러 주요 호스트(Namecheap, KnownHost, HostPapa, InMotion)가 모든 테넌트의 업데이트를 기다리는 대신 영향을 받는 포트로의 인바운드 트래픽을 선제적으로 차단하기로 선택한 이유입니다.
이 세 번째 지점은 깊이 생각해 볼 가치가 있습니다. cPanel은 제어판 시장의 약 94%를 장악하고 있는 것으로 추정됩니다. 한 공급업체의 세션 처리 코드에 있는 단일 로직 결함이 수 주 동안 사실상 업계 전반의 루트 접근 취약점이 되었습니다. 이러한 집중 위험은 이 특정 CVE와 무관하게 반드시 내면화해야 할 반복되는 주제입니다.
cpsrvd는 세 가지 cPanel 제품 표면을 모두 동일한 바이너리에서, 그리고 중요하게는 동일한 세션 처리 코드 경로에서 제공하는 장기 실행 Perl 데몬입니다:
| 포트 쌍 | 표면 | 대상 |
|---|---|---|
| 2082 / 2083 | cPanel | 최종 고객 (계정별) |
| 2086 / 2087 | WHM | 루트/리셀러 관리자 |
| 2095 / 2096 | Webmail | 이메일 사용자 |
세 표면 모두 취약한 세션 로직을 공유하므로 이 여섯 포트 중 어느 하나라도 노출되면 악용에 충분합니다. 그중 "덜 노출된" 표면이라는 것은 의미가 없습니다. 잘 분리된(well-segmented) 환경에서는 이 포트들 중 어느 것도 원래 인터넷에서 직접 도달할 수 없어야 합니다. 그러나 실제로는 관리 편의성, 하이브리드 호스팅 구성, 방화벽 관리 소홀(firewall drift)로 인해 많은 환경이 노출되어 있었습니다.
cPanel 세션은 성능상의 이유로 보이는 두 개의 병렬 디스크 표현으로 유지됩니다:
/var/cpanel/sessions/raw/<session-id>) — 줄 단위의 일반 텍스트 key=value 형식으로, 속성마다 한 줄입니다./var/cpanel/sessions/cache/<session-id>, 개념적으로) — 구조화된 JSON 문서로, 파싱 비용이 더 저렴하기 때문에 일반 요청 경로에서 우선적으로 읽습니다.정상적인 운영에서는 JSON 캐시가 권위 있는(authoritative) 소스이고 원시 파일은 내구성 보장을 위한 백스톱입니다. 취약점은 정확히 원시 파일이 다시 파싱되어 JSON 캐시를 재생성하는 데 사용되는 상황이 존재하고, 두 형식이 포함된 개행 문자의 의미에 대해 서로 다르게 해석하기 때문에 발생합니다.
CVE-2026-41940은 단일 실수가 아닙니다. 이는 각각이 개별적으로는 그럴듯한 설계 결정인 네 가지 별개의 약점이 결합하여 완전한 인증 우회를 만들어내는 산물입니다. 이러한 "스위스 치즈" 구조는 이 특정 제품을 넘어 방어자와 코드 리뷰어에게 매우 유익합니다.
cPanel의 세션 하위 시스템에는 세션 값에서 위험한 문자(캐리지 리턴, 줄 바꿈, =)를 제거하는 살균 루틴이 이미 있었습니다. 문제는 해당 루틴이 어디서 호출되었는지입니다. 이 루틴은 더 높은 수준의 래퍼 함수(세션 "생성"/"수정" API) 안에 있었으며, 세션 데이터를 직접 쓰지 않고 해당 래퍼를 거치도록 하는 것은 호출자의 책임이었습니다.
cpsrvd 내부의 HTTP 기본 인증 핸들러 — Authorization HTTP 헤더에서 직접 자격 증명을 받아들이는 코드 경로 — 는 제출된 비밀번호를 살균 래퍼를 완전히 우회하는 하위 수준 저장 루틴을 통해 사전 인증 세션 파일에 저장했습니다. 살균이 디스크 기록 시점에 필수가 아니라 선택 사항이었기 때문에 이 호출자는 조용히 살균을 건너뛰었습니다.
이것은 "소스에서 검증하지 말고 싱크(sink)에서 검증하라"는 교과서적인 실패 패턴입니다. 보안 통제가 단순히 다른 함수를 호출함으로써 우회될 수 있는 한, 그것은 실수, 리팩터링, 또는 이 특정 통제에 대해 감사할 생각을 한 사람이 없는 코드 경로를 통해서든 언젠가는 우회됩니다. cPanel이 배포한 영구 수정은 살균 호출을 저장 함수 내부로 이동시켜 현재와 미래의 어떤 호출자도 더 이상 건너뛸 수 없게 만듭니다.
세션 기록기는 민감한 필드(특히 비밀번호 필드)를 세션별 대칭 키로 암호화합니다. 해당 키는 클라이언트가 제시하는 세션 쿠키에 포함된 구성 요소에서 파생됩니다. 취약한 코드에서는 해당 키 구성 요소가 요청에 없으면 — 공격자가 보낼 쿠키를 스스로 선택하므로 전적으로 공격자의 통제 하에 있는 사항 — 기록 자체를 거부하는 대신 암호화 단계가 조용히 건너뛰어졌습니다.
다시 말해, 공격자가 자신의 세션 쿠키 일부를 의도적으로 생략하거나 잘라내면 제출한 데이터가 암호화되지 않은 채 디스크에 기록되도록 만들 수 있습니다. 입력을 공급하는 신뢰할 수 없는 당사자가 활성화를 꺼버릴 수 있는 암호화는 의미 있는 보안 경계가 아닙니다. 실패 시 닫힘(fail closed, 기록 거부 또는 요청 거부) 방식이어야지 실패 시 열림(fail open, 보호 없이 기록) 방식이어서는 안 됩니다.
이것이 CRLF 인젝션에서 "인젝션"의 핵심입니다. 원시 세션 파일은 줄로 구분됩니다. 캐리지 리턴/줄 바꿈 시퀀스는 하나의 key=value 레코드를 종료하고 다음 레코드를 시작합니다. 반면 JSON 캐시 형식은 동일한 문자 시퀀스를 단일 JSON 문자열 값 내부의 이스케이프된 하위 문자열로 표현합니다. 의미상으로는 불활성(inert)이며 단지 데이터일 뿐입니다.
세션이 JSON 캐시에만 존재하는 한 필드(예: 비밀번호)에 포함된 CRLF는 무해합니다. 단지 문자열 안의 바이트일 뿐입니다. 위험은 원시 파일을 다시 파싱하여 캐시를 재생성하는 코드 경로에 나타납니다. 공개된 기술 분석에 따르면 이는 URL에 바인딩된 보안 토큰 검사에 실패하여 요청이 거부될 때 발생합니다. 해당 거부를 처리하는 핸들러는 캐시를 건너뛰고 원시 파일을 줄 단위로 다시 읽어 세션을 재로드한 다음, 그 재파싱 결과로 JSON 캐시를 다시 씁니다.
그 순간, 공격자가 제출한 "비밀번호"에 포함시킨 CRLF 시퀀스는 한 필드 안의 불활성 바이트가 아니라 레코드 구분자가 되어, 하나의 값이었어야 할 것을 여러 개의 독립적인 key=value 줄로 분할합니다. 그 각 줄 — 공격자가 이름과 값을 완전히 통제하는 줄을 포함하여 — 은 재생성된 JSON 세션 캐시의 최상위 항목으로 승격되며, 코드베이스의 나머지 부분은 이를 정당하게 설정된 세션 속성과 구별할 수 없습니다.
일반적인 교훈: 두 파서가 동일한 바이트 시퀀스를 다르게 해석하도록 만들 수 있을 때마다(원시 대 캐시, form-encoded 대 JSON, 한 이스케이프 규칙 대 다른 규칙), 그 불일치는 잠재적인 인젝션 프리미티브입니다. 어느 파서가 "더 올바른지"는 중요하지 않습니다. 중요한 것은 신뢰할 수 없는 데이터가 두 번째 파서의 문법에 대해 재검증되지 않은 채 두 표현 사이를 교차할 수 있다는 것입니다.
체인의 마지막 연결 고리는 비밀번호 검사 로직 자체에 있습니다. 세션에 최근 성공한 내부 인증 타임스탬프를 기록하는 필드가 이미 있으면 비밀번호 챌린지는 완전히 건너뜁니다. 해당 필드의 존재만으로 인증이 이미 성공했다는 충분한 증거로 취급됩니다. 동반되는 2FA 확인 플래그도 단순히 존재한다는 이유만으로 2FA 챌린지를 억제합니다.
두 필드 모두 정당한 내부 목적(cPanel 구성 요소 간 SSO 핸드오프, 다른 수단을 통해 사용자를 이미 검증한 내부 도구)을 위해 존재합니다. 설계 결함은 두 필드 모두 실제 인증 이벤트에 암호화 방식으로 바인딩되어 있지 않으며, 계층 3을 통해 공격자가 임의의 세션 속성을 쓸 수 있게 되면 단순히 위조될 수 있다는 것입니다. "신뢰하세요, 이미 확인되었습니다"라는 의미의 플래그는 신뢰받는 당사자가 설정할 수 없을 때만 의미가 있습니다.
이 네 가지 약점 중 어느 것도 단독으로는 치명적이지 않습니다:
이들이 함께 연결되면 완전하고, 인증되지 않은, 원격 루트 장악이 됩니다. 이것은 정확히 개별 함수에 국한된 단위 테스트로는 잡을 수 없는 종류의 취약점입니다. 어떤 단일 함수도 단독으로는 "잘못"되지 않기 때문입니다. 결함은 각각 독립적으로 추론된 하위 시스템 간의 상호작용에 존재합니다.
다음은 공급업체 및 업계 권고에서 이미 공개된 세부 수준의 논리적 악용 단계를 설명하며, 실제 페이로드 바이트, 인코딩된 헤더 또는 실행 가능한 요청 시퀀스를 재현하지 않습니다.
| 단계 | 공격자가 달성하는 것 | 악용되는 근본 결함 |
|---|---|---|
| 1. 사전 인증 세션 생성 | 일반적인 (의도적으로 실패시키는) 로그인 시도를 통해 디스크에 세션 파일 생성을 유발 — 유효한 자격 증명 불필요. | 세션 파일은 인증이 성공하기 전에 생성되며, 이후 정당한 로그인의 기반으로 신뢰됨. |
| 2. CRLF가 포함된 데이터를 원시 세션 파일에 밀반입 | 암호화 단계를 우회하는 요청 프레이밍을 사용하여 HTTP Basic-auth 코드 경로를 통해 공격자 제어 데이터를 제출하고, 그 데이터가 살균되지도 않고 암호화되지도 않은 채 디스크에 기록되도록 함. | 계층 1 및 2 (누락된 살균 호출; 건너뛸 수 있는 암호화). |
| 3. 원시 파일 재파싱 강제 | cpsrvd가 JSON 캐시를 우회하고 원시 세션 파일을 줄 단위로 다시 읽은 다음 그 재파싱 결과로 캐시를 재생성하도록 만드는 특정 거부 코드 경로를 트리거. | 계층 3 (원시 표현과 캐시 표현 간 형식 불일치). |
| 4. 권한 승격 완료 | 재생성된 JSON 캐시는 이제 공격자가 선택한 최상위 필드를 포함하여 세션을 root 소유로, 루트 권한을 가진 것으로, 2FA를 통과한 것으로, 최근 성공한 인증 타임스탬프가 있는 것으로 표시 — 공격자가 선택한 보안 토큰도 포함. | 3단계의 직접적인 결과. |
| 5. 위조된 세션 사용 | 이 세션과 공격자가 선택한 보안 토큰을 제시하는 모든 후속 요청은 cpsrvd에 의해 완전히 인증된 루트 관리자로 처리됨: 최근 타임스탬프 필드가 비밀번호 프롬프트를 억제하고, 확인 플래그가 2FA를 억제하며, 토큰이 요청별 CSRF 스타일 검사를 충족. | 계층 4 (바인딩되지 않은 신뢰 플래그), 4단계의 위조를 증폭. |
5단계부터 공격자는 일반적이고 완전히 허가된 WHM API 접근 권한을 보유합니다. WHM의 정당한 기능 세트 — 사용자 정의 훅, 패키지/템플릿 관리, PHP 핸들러 구성, 크론 및 계정 관리, DNS 영역 편집 — 는 추가 취약점 없이 전적으로 "지원되는" 관리 기능을 통해 이를 대화형 루트 코드 실행으로 확대하기에 충분합니다.