Zoom annotation 취약점을 이용한 회의 참가자 간 RCE


요약
Zoom의 annotation 처리 라이브러리에서 발견된 CVE-2026-53413, CVE-2026-53414, CVE-2026-53415가 2026-08-11 공개됐다. 같은 회의에 참가한 공격자는 조작한 annotation PDU를 다른 참가자의 클라이언트에 전달해 메모리를 손상시키거나 정보를 노출하고, 조건에 따라 RCE로 연결할 수 있다.
피해자는 annotation 도구를 직접 사용하거나 파일과 링크를 열 필요가 없다. 다만 인터넷에서 임의의 Zoom 클라이언트를 직접 공격하는 pre-auth RCE는 아니다. 공격자가 대상과 같은 회의에 들어갈 수 있어야 한다.
| 항목 | 내용 |
|---|---|
| CVE | CVE-2026-53413, CVE-2026-53414, CVE-2026-53415 |
| 취약 컴포넌트 | Zoom annotation 엔진 |
| 주요 라이브러리 | libannotate.so, 플랫폼별 동등 컴포넌트 |
| 공격 입력 | 조작된 annotation PDU와 직렬화 객체 |
| 공격자 조건 | 대상과 같은 회의에 참가 |
| 사용자 조작 | 불필요 |
| 영향 | stack·heap memory corruption, 정보 노출, DoS, RCE |
| 벤더 bulletin 공개일 | 2026-08-11 |
| 연구 분석 공개일 | 2026-08-11 |
| 실제 악용 | 공개된 in the wild 악용 사례 없음 |
회의 참가자가 annotation parser에 입력을 보낼 수 있다
회의 참가 권한은 클라이언트 parser에 도달하는 접근 권한으로 작동한다. 공개 회의, 외부 협력사 회의, 웨비나처럼 신뢰 수준이 다른 사용자가 참여하는 환경에서는 회의 입장 통제와 클라이언트 버전을 함께 관리해야 한다.
공개 및 패치 일정
| 날짜 | 내용 |
|---|---|
| 2026-06-08 | 연구진이 annotation memory corruption 발견 |
| 2026-06-09 | Zoom Client 7.0.5에서 RCE 확인 |
| 2026-06-10 | Zoom에 취약점 보고 |
| 2026-06-22 | Zoom Workplace 7.1.0에 CVE-2026-53413·53414 수정 반영 |
| 2026-07-15 | 구버전 클라이언트를 보호하는 서버 측 필터 배포 |
| 2026-07-20 | Zoom Workplace 7.1.5에 CVE-2026-53415 수정 반영 |
| 2026-08-11 | CVE와 기술 분석 공개 |
서버 측 필터는 Zoom 서버가 회의 콘텐츠를 검사할 수 있을 때만 적용된다. E2EE 회의에서는 서버가 annotation 메시지를 해독할 수 없어 취약한 클라이언트까지 조작된 메시지가 전달될 수 있다.
취약한 메시지 처리 경로
Zoom은 annotation 객체를 이미지가 아닌 typed object로 전송한다. 자유 곡선은 CAnnoObjSmoothPen, 텍스트 상자는 CAnnoObjTextbox처럼 표현되며, 공통 헤더는 CAnnoObj에 저장된다. 객체는 CAnnoPduAddObj 등의 PDU로 직렬화돼 Zoom MMR을 거쳐 수신 클라이언트로 전달된다.
수신 측 CAnnoPduFactory::create는 wire에서 opcode를 읽고 해당 객체의 deserializer를 호출한다. 공개 분석에서 확인된 opcode는 다음과 같다.
| PDU | Opcode | 역할 |
|---|---|---|
AddObj | 0x10001 | annotation 객체 추가 |
AddObjAck | 0x10002 | 객체 수신 응답 |
문제의 처리 경로에는 sender role이나 메시지 origin을 검증하는 로직이 없었다. 공격자는 acknowledgement가 전달될 위치에 AddObj opcode와 직렬화된 객체를 넣어 수신 측이 전체 객체 그래프를 역직렬화하도록 만들 수 있었다.
전달 방향은 참가자의 역할에 따라 다르다.
### viewer
-> MMR
-> sharer
-> annotation deserializer
### sharer
-> MMR
-> selected viewer
-> annotation deserializer
viewer 위치에서는 주로 화면 공유자의 parser에 도달한다. sharer 위치에서는 참가자별 downstream channel을 이용해 개별 viewer를 지정할 수 있다.
CVE-2026-53413
CVE-2026-53413은 CAnnoFormatBlock::Deserialize의 bounds check 누락으로 발생한다. 이 구조체에는 UTF-16 문자열을 저장하는 128바이트 고정 버퍼 네 개가 있다. parser는 wire에서 32비트 문자 개수를 읽고 2 × count 바이트를 복사하지만, 계산된 크기를 128바이트 destination과 비교하지 않았다.
텍스트 annotation의 역직렬화 경로는 다음과 같다.
### CAnnoObj
-> CAnnoTextFrame
-> CAnnoTextRange
-> CAnnoFormatBlock::Deserialize
-> Stream_Read
CAnnoTextRange가 CAnnoTextFrame::Deserialize의 704바이트 local object로 생성되면 oversized fourth count가 stack frame의 saved register와 return address까지 덮을 수 있다. extension flag가 설정된 경로에서는 별도의 592바이트 CAnnoExtChild가 heap에 할당되며, 같은 결함이 heap overflow primitive로 바뀐다.
연구진은 다음 필드 조합이 정상 PDU parser를 통해 취약 경로에 도달한다고 확인했다.
PDU opcode: 0x10001
object type: text annotation
object flags: bit 3, TextFrame
target field: fourth CAnnoFormatBlock count
copy size: 2 × attacker-controlled count
destination size: 128 bytes
공개 분석에는 745바이트 AddObj PDU로 stack protector에 의한 비정상 종료를 유도한 결과가 포함돼 있다. 무기화된 PoC 코드는 공개되지 않았다.
macOS arm64의 취약 annoter bundle에는 PAC와 stack canary가 적용되지 않은 것으로 분석됐다. 연구진은 overflow로 PC, X19–X30을 제어하고 shared cache의 gadget을 통해 execvp를 호출했다. 검증 단계에서는 Zoom 프로세스를 Safari 실행으로 대체해 코드 실행을 입증했다.
Android에서는 heap에 같은 크기의 CAnnoExtChild 객체를 배치한 뒤 인접 객체의 vtable pointer 하위 바이트를 덮는 방식이 확인됐다. 이후 RemoveObj 또는 ModifyObj의 destructor 경로에서 virtual call을 발생시켜 control flow를 전환할 수 있었다.
CVE-2026-53414
CVE-2026-53414는 glyph buffer 크기와 실제 입력 길이가 일치하지 않아 발생하는 buffer over-read다. 수신 측은 공격자가 제공한 문자 개수로 2 × count + 2 바이트를 할당하지만 메모리를 초기화하지 않는다. 이후 packet에 실제로 포함된 바이트만 복사하고 NUL은 할당 영역의 끝에 기록한다.
큰 count와 짧은 body를 조합하면 중간의 초기화되지 않은 heap 데이터가 문자열 처리 경로에 남는다. 연구진은 이 경로에서 code pointer, vtable pointer, resource string을 포함한 heap 내용이 노출되는 것을 확인했다. 이 정보는 CVE-2026-53413 exploit에서 ASLR 기준 주소를 계산하는 primitive로 사용될 수 있다.
단독 영향은 정보 노출과 DoS다. CVE-2026-53413의 memory corruption과 연결하면 안정적인 control-flow hijack에 필요한 주소 정보를 제공한다.
CVE-2026-53415
CVE-2026-53415는 annotation parser의 별도 use-after-free 취약점이다. 내부 번호 75인 auto-shape metadata 객체 CAnnoObjAutoMetaShape를 처리할 때, 공격자 입력을 linked-list 내부 구조로 읽은 뒤 pointer를 검증하지 않고 unlink한다.
공격자는 unlink 과정에서 쓰일 pointer와 값을 조작할 수 있어 write-what-where primitive를 얻는다. 이는 CVE-2026-53413·53414와 독립적으로 RCE에 연결될 수 있다.
Zoom은 연구진의 보고 전에 해당 결함을 파악하고 서버 측 필터를 배포했지만 E2EE 회의에는 필터를 적용할 수 없었다. 클라이언트 측 수정은 Zoom Workplace 7.1.5에 포함됐다.
영향 버전
Zoom bulletin과 연구진이 제시한 수정 기준은 다음과 같다.
| 제품 | 수정 기준 |
|---|---|
| Zoom Workplace 7.1 계열 | 7.1.5 이상 |
| Zoom Workplace 7.0 계열 | 7.0.6 이상 |
| Zoom Workplace VDI Client 7.0 계열 | 7.0.11 이상 |
| Zoom Workplace VDI Client 6.6 계열 | 6.6.16 이상 |
| Zoom Rooms | 7.1.0 이상 |
| Zoom Meeting SDK | 7.1.0 이상 |
지원 플랫폼에는 Windows, macOS, Linux, iOS, Android가 포함된다. 동일한 annotation 코드가 여러 native client에 사용되므로 데스크톱 클라이언트만 확인해서는 안 된다.
자산 식별
EDR이나 소프트웨어 배포 시스템에서 사용자별 설치본, 시스템 설치본, VDI 이미지와 회의실 장비를 구분해 수집한다. Windows에서는 다음 명령으로 대표적인 설치 위치와 실행 파일 버전을 확인할 수 있다.
$zoomPaths = @(
"$env:APPDATA\Zoom\bin\Zoom.exe",
"$env:ProgramFiles\Zoom\bin\Zoom.exe",
"${env:ProgramFiles(x86)}\Zoom\bin\Zoom.exe"
)
Get-Item -ErrorAction SilentlyContinue $zoomPaths |
Select-Object FullName,
@{Name='ProductVersion'; Expression={$_.VersionInfo.ProductVersion}},
LastWriteTime
%APPDATA%의 사용자별 설치본은 시스템 단위 소프트웨어 목록에서 빠질 수 있다. Zoom Rooms, Meeting SDK 기반 애플리케이션, VDI Meeting Client도 별도 inventory가 필요하다.
탐지 포인트
고정 IOC나 공개된 wire signature는 없다. annotation PDU는 Zoom transport 안에서 전달되며 E2EE 회의에서는 서버 측 payload 검사도 불가능하다. 회의 기록, 클라이언트 crash, Zoom 프로세스의 후속 행위를 시간 기준으로 연결해야 한다.
네트워크
- 회의 참가 직후 Zoom 프로세스에서 시작된 신규 외부 연결
- 평소 사용하지 않던 destination이나 port로 향하는 Zoom 프로세스의 연결
- 여러 참가자 단말의 crash 시점과 일치하는 동일 회의 세션
- E2EE가 설정된 회의에서 발생한 비정상 클라이언트 종료
annotation 사용량이나 encrypted packet 크기만으로 악성 PDU를 안정적으로 구분하기는 어렵다.
엔드포인트
Zoom.exe또는zoom.us가 shell, script interpreter, 브라우저를 실행하는 행위- Zoom 프로세스가 기존 image와 다른 실행 파일로 대체되는 행위
- 회의 중 Zoom 프로세스에서 발생한 stack corruption 또는 access violation
- Zoom 프로세스가 executable이나 script를 생성한 뒤 실행하는 행위
- 회의 참가 직후 생성된 비정상 child process
사냥 규칙은 다음처럼 구성할 수 있다.
process_detection:
parent_names:
- Zoom.exe
- zoom.us
- zoom
suspicious_children:
- powershell.exe
- pwsh.exe
- cmd.exe
- wscript.exe
- cscript.exe
- sh
- bash
- osascript
correlate_with:
- active_zoom_meeting
- recent_zoom_crash
- unexpected_network_connection
- newly_written_executable
정상적인 URL 열기와 외부 인증 과정에서도 브라우저가 실행될 수 있다. child process의 command line, 실행 시점, 회의 상태와 파일 생성 내역을 함께 확인한다.
서버
- 외부 참가자가 포함된 회의의 입장·퇴장 기록
- 공격 의심 시점의 화면 공유자 변경 기록
- E2EE 활성화 여부
- 같은 회의에 연결된 여러 단말의 동시 crash
- 개인 회의 ID나 공개 링크를 통한 비정상 참가
MMR 로그에 접근할 수 있더라도 E2EE payload의 annotation opcode나 객체 필드를 서버에서 확인할 수는 없다.
대응
클라이언트를 제품군별 수정 버전 이상으로 올린다. 자동 업데이트 상태만 보지 말고 실제 실행 파일 버전을 수집해 배포 결과를 검증한다.
- 사용자별 Zoom Workplace 설치본을 inventory에 포함한다.
- VDI image와 VDI Meeting Client를 함께 갱신한다.
- Zoom Rooms와 Meeting SDK 기반 애플리케이션을 확인한다.
- 조직 정책으로 플랫폼별 최소 클라이언트 버전을 설정한다.
- 외부 참가자와 guest에도 최소 버전 정책을 적용한다.
- 업데이트가 끝날 때까지 E2EE 사용을 제한해 서버 측 필터가 동작하도록 한다.
- 불특정 참가자가 들어오는 회의에서는 annotation, whiteboard, remote control과 file transfer를 제한한다.
- 회의 대기실, passcode, authenticated-users-only 정책으로 parser에 입력을 보낼 수 있는 참가자를 줄인다.
회의 암호와 대기실은 공격자의 회의 진입을 제한하지만 취약한 역직렬화 로직을 수정하지 않는다. E2EE도 같은 회의에 들어온 공격자에게는 방어 수단이 아니며, 이 사례에서는 서버 측 필터를 우회시키는 조건이 된다.
의심 단말에서는 Zoom 프로세스 tree, crash dump, 생성 파일, outbound connection을 보존한다. 이후 같은 시간대의 회의 참가 기록과 화면 공유자 정보를 대조해 공격 입력을 보낼 수 있었던 참가자를 좁힌다.
참고 자료
- ZOOMSDAY: How A Security Found a Nation-State Vulnerability in Zoom in One Day
- Zoom Security Bulletin ZSB-26015
- Zoom Security Bulletin ZSB-26016
- Zoom Security Bulletin ZSB-26017
- NCSC-2026-0293: Vulnerabilities Exploited in Zoom
- Critical Zoomsday Flaw Enables Device Takeover During Zoom Calls