[하루한줄] CVE-2025-2783 : Chrome의 Mojo IPC 내 핸들 검증 미흡으로 인한 샌드박스 탈출
URL
https://blog.securelayer7.net/cve-2025-2783-chrome-mojo-ipc-sandbox/
Target
- Chrome on Windows < 134.0.6998.177
Explain
Background
이 취약점은 Kaspersky 연구원(Boris Larin, Igor Kuznetsov)이 러시아의 미디어, 교육, 정부 기관을 대상으로 한 “Operation ForumTroll” 공격 캠페인을 분석하던 중 발견된 제로데이 취약점입니다. 공격자는 피해자가 악성 링크를 클릭하는 것만으로(User Interaction 필요) Chrome의 샌드박스 환경을 탈출하여 호스트 시스템에서 임의 코드를 실행하고 시스템을 장악할 수 있었습니다.
Chrome은 보안을 위해 권한이 낮은 Renderer Process와 시스템 접근 권한이 있는 Browser Process로 나뉘어 있으며, 이 둘은 Mojo IPC를 통해 통신합니다. 이 취약점은 Renderer가 조작된 IPC 메시지를 보내 Broker가 의도치 않은 Windows API(DuplicateHandle)를 호출하게 만드는 것이 핵심입니다.
정리하면 공격 흐름은 이렇습니다.
- 공격자는 악의적인 파일이나 사이트를 만들어서 크롬 Mojo의 가짜 핸들로 보냅니다.
- 이게 열리면, 낮은 권한의 프로세스에서 핸들을 통해 높은 프로세스로 전달됩니다.
- 크롬은 핸들을 체크하지 않아서 높은 프로세스는 그 메시지를 허용합니다.
- 공격자는 이를 통해 샌드박스를 우회하고 임의 코드를 실행합니다.
Root Cause
Phase 1: 취약한 IPC 인터페이스 (ipcz 레이어)
Chrome은 최근 Mojo의 백엔드로 ipcz(IPCZ: Inter-Process Communication Zero-copy)를 도입했습니다. 공격자는 이 레이어의 NodeLink::RelayMessage 함수를 타겟팅했습니다.
- 정상적인 흐름:
IPC 메시지는MessagePipe를 통해 직렬화되어 전송됩니다. 이때 핸들과 같은 리소스는 OS 레벨에서 복제되어 전달되는데, 수신 측은 메시지 헤더(Message ID)를 보고 어떤 데이터를 기대해야 할지 알고 검증해야 합니다. 취약점 트리거 (Bug):
공격자는 정의되지 않은 Message ID (0x69)를 포함한RelayMessage를 생성합니다.// 공격자 코드 (Renderer 내부) // ID: 0x69 (Undefined) ipcz::Message::Message_unsigned_char__unsigned_long_long_(v23, 0x69, ...); // ... 핸들 데이터 조작 ... ipcz::NodeLink::RelayMessage(...); // 메시지 전송
Phase 2: Broker의 검증 부재 및 DuplicateHandle 오용
Browser Process가 이 메시지를 수신했을 때, 핸들러는 0x69 ID를 가진 메시지를 처리하면서 치명적인 실수를 범합니다.
- Blind Unmarshalling: 수신 측 함수(
0x18001E350)는 메시지 페이로드의 오프셋0xC8위치에 있는 값을WrappedPlatformHandle객체로 간주하고 읽어들입니다. 검증 없는 핸들 복제: 읽어들인 값(공격자가 보낸 핸들 값)이 유효한지, 혹은 샌드박스된 프로세스가 접근해서는 안 되는 핸들인지 검증하지 않고
DuplicateHandleAPI를 호출합니다.// Browser Process (취약한 핸들러 의사 코드) HANDLE from_message = ExtractHandleFromMsg(message + 0xC8); // 검증 없음 HANDLE TargetHandle; // 현재 프로세스(Browser)의 권한으로 핸들을 복제해버림 if (DuplicateHandle(GetCurrentProcess(), from_message, GetCurrentProcess(), &TargetHandle, ...)) { // 성공 시, 공격자가 원하는 핸들이 Browser 프로세스 내에서 유효해짐 }
이 정에서 공격자는 Broker(Browser) 프로세스가 소유한 강력한 핸들이나, Broker 자신의 프로세스 핸들을 획득하거나 조작할 수 있는 Primitive를 얻게 됩니다.
Exploitation: Code Execution
DuplicateHandle을 통해 Broker 프로세스(혹은 상위 권한 프로세스)에 대한 제어권(Handle)을 얻은 공격자는 다음과 같은 절차로 코드를 실행합니다.
- Thread Hijacking: 공격자는 획득한 상위 프로세스의 핸들을 이용해 해당 프로세스 내의 thread contect을 제어합니다.
SuspendThread(TargetThread): 타겟 스레드 멈춤GetThreadContext(...): 현재 레지스터 상태 백업SetThreadContext(...): RIP를 ROP 가젯이나 쉘코드가 있는 주소로 변경
- Shellcode Injection:
WriteProcessMemory: 샌드박스 밖의 메모리 영역에 악성 쉘코드를 씁니다.- 가젯(
EBFE등)을 이용해 스레드를 무한루프에 빠뜨리거나 특정 흐름으로 유도한 뒤, 최종적으로ResumeThread를 호출하여 쉘코드를 실행합니다.
Outro
일반적인 샌드박스 탈출은 커널(Win32k.sys 등) 취약점을 이용하거나, 복잡한 로직 버그를 연쇄적으로 이용해야 합니다. 하지만 이 취약점은 “Mojo IPC 메시지 하나”로 논리적인 권한 상승이 가능했습니다. 따라서 이 취약점은 핸들 유효성에 대해 검증 도입이 되었고
if (!IsValidMojoHandle(handle)) return; // Invalid 메시지 차단
기능 실행 조건 강화는 식으로 패치가 되었습니다.
bool IsEscapeCodeAllowed(const std::string& code) {
return code == "safe_mode" || code == "internal_debug";
}
Reference
https://nvd.nist.gov/vuln/detail/CVE-2025-2783
https://securelist.com/operation-forumtroll/115989/
https://www.kaspersky.com/blog/forum-troll-apt-with-zero-day-vulnerability/53215/
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.