CVE-2026-5281: 크롬 Dawn WebGPU 제로데이 취약점과 Use-After-Free 공격

서론

어제 새벽, 한 금융사 보안팀에서 의심스러운 크롬 브라우저 프로세스를 발견했습니다. 일반적인 웹 서핑 중이던 직원의 PC에서 비정상적인 메모리 접근 패턴이 감지된 것입니다. 초기 분석 결과, 악성 웹페이지 방문만으로 임의 코드 실행이 가능한 제로데이 취약점이 원인이었습니다.

구글이 2025년 12월 긴급 보안 업데이트를 발표하며 CVE-2026-5281을 패치했습니다. 이 취약점은 이미 실제 공격에 악용된 상태였으며, 크롬의 WebGPU 구현체인 Dawn에서 발생한 Use-After-Free 버그입니다.

이 취약점이 특히 위험한 이유는 사용자 개입 없이 웹페이지 방문만으로 exploitation이 가능하다는 점입니다. WebGPU는 최신 웹 표준으로, GPU 가속 렌더링과 머신러닝 연산을 브라우저에서 직접 수행할 수 있게 해주는 강력한 기능입니다. 하지만 이러한 저수준 하드웨어 접근 능력은 공격자에게도 매력적인 타겟이 됩니다.

이 글에서는 Use-After-Free 취약점의 기본 원리부터 CVE-2026-5281의 구체적인 공격 시나리오, 그리고 실제 대응 방안까지 기술적으로 깊이 있게 분석해보겠습니다.


WebGPU와 Dawn 아키텍처 이해

WebGPU란 무엇인가

WebGPU는 차세대 웹 그래픽스 API로, WebGL의 후속 기술입니다. 현대적인 GPU 기능을 웹에서 직접 사용할 수 있게 해주며, 게임, 3D 렌더링, 머신러닝 추론 등에 활용됩니다.

1
2
3
4
5
6
7
8
9
graph TD
    A[Web Application] --> B[WebGPU API]
    B --> C[Dawn Library]
    C --> D[GPU Driver]
    D --> E[Hardware GPU]
    
    F[JavaScript Code] --> B
    B --> G[Shader Compilation]
    G --> C

Dawn 라이브러리의 역할

Dawn은 WebGPU의 오픈 소스 크로스 플랫폼 구현체입니다. 크롬, Edge 등 Chromium 기반 브라우저들이 WebGPU 기능을 제공하기 위해 Dawn을 사용합니다. Dawn은 다음과 같은 계층 구조를 가집니다:

| 계층 | 역할 | 예시 | | :— | :— | :— | | Web API Layer | JavaScript 인터페이스 제공 | navigator.gpu | | Dawn Core | WebGPU 명령어 처리 | Buffer, Texture 관리 | | Backend Abstraction | GPU API 추상화 | Vulkan, Metal, DX12 | | Native GPU API | 실제 GPU 드라이버 호출 | Vulkan Commands |


Use-After-Free 취약점 심층 분석

메모리 관리의 근본적 문제

Use-After-Free(UAF)는 C/C++ 프로그램에서 가장 위험한 메모리 안전 취약점 중 하나입니다. 이름 그대로 “해제된 메모리를 다시 참조하는” 버그입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// UAF 취약점 예시 (학습용)
#include <stdlib.h>

typedef struct {
    int (*callback)(void*);
    void* data;
} GPUContext;

void process_gpu_command() {
    GPUContext* ctx = (GPUContext*)malloc(sizeof(GPUContext));
    ctx->callback = legitimate_handler;
    ctx->data = some_buffer;
    
    // 첫 번째 사용
    ctx->callback(ctx->data);
    
    // 메모리 해제
    free(ctx);
    
    // 취약점: 해제된 메모리 재참조
    // 다른 코드에서 같은 주소를 할당받아 내용을 변경했다면?
    ctx->callback(ctx->data);  // DANGEROUS!
}

공격 원리

1
2
3
4
5
6
7
graph LR
    A[객체 할당] --> B[객체 사용]
    B --> C[객체 해제]
    C --> D[공격자 할당]
    D --> E[가짜 객체 생성]
    E --> F[댕글링 포인터 호출]
    F --> G[코드 실행]
  1. 객체 생성: 프로그램이 메모리를 할당하고 초기화 2. 정상 사용: 객체의 메서드나 데이터에 접근 3. 메모리 해제: 객체가 더 이상 필요 없어 free() 호출 4. 포인터 미정리: 해제된 메모리를 가리키는 포인터가 여전히 존재 5. 공격자 개입: 같은 크기의 메모리를 할당하여 공격자가 제어하는 데이터로 채움 6. UAF 트리거: 댕글링 포인터를 통해 가짜 객체의 함수 포인터 호출 7. 코드 실행: 공격자가 원하는 코드 실행

CVE-2026-5281 공격 시나리오

취약점 발생 지점

Dawn 라이브러리에서 WebGPU 리소스 관리 중 특정 객체의 수명 주기 관리가 제대로 이루어지지 않았습니다. 구글은 상세한 기술 정보를 공개하지 않았지만, 유사한 Dawn UAF 취약점 패턴을 통해 추론해볼 수 있습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 개념 증명 코드 (PoC) - 학습 및 방어 목적
// 실제 익스플로잇은 더 복잡한 힙 스프레이 기법 필요

async function triggerUAF() {
    const adapter = await navigator.gpu.requestAdapter();
    const device = await adapter.requestDevice();
    
    // 1. GPU 버퍼 생성
    const buffer1 = device.createBuffer({
        size: 1024,
        usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
    });
    
    // 2. 버퍼에 데이터 쓰기
    const data = new Float32Array(256);
    device.queue.writeBuffer(buffer1, 0, data);
    
    // 3. 버퍼 참조를 다른 객체에 저장
    const texture = device.createTexture({
        size: { width: 64, height: 64 },
        format: 'rgba8unorm',
        usage: GPUTextureUsage.STORAGE_BINDING
    });
    
    // 4. 명령 인코더 생성 및 복잡한 연산
    const encoder = device.createCommandEncoder();
    
    // 5. 경쟁 조건 유발 시도
    // 비동기 작업 중 객체 해제와 접근이 동시에 발생하도록 유도
    buffer1.destroy();  // 버퍼 해제
    
    // 6. 해제된 버퍼에 대한 후속 작업
    // 취약한 버전에서는 이 시점에서 UAF 발생 가능
    const computePass = encoder.beginComputePass();
    // ... compute shader에서 이미 해제된 버퍼 참조
    computePass.end();
    
    device.queue.submit([encoder.finish()]);
}

공격 파이프라인

1
2
3
4
5
6
7
8
9
graph TD
    A[악성 웹페이지 접속] --> B[WebGPU 초기화]
    B --> C[ 스프레이]
    C --> D[UAF 트리거]
    D --> E[RCE 달성]
    E --> F[시스템 장악]
    
    B --> G[정상 GPU 리소스]
    G --> D

위험도 평가

| 평가 항목 | 상세 내용 | 점수/등급 | | :— | :— | :— | | 공격 복잡도 | 낮음 (웹페이지 방문만으로 가능) | Low | | 사용자 개입 | 불필요 (Zero-click) | None | | 권한 상승 | 브라우저 샌드박스 탈출 가능 | High | | 실제 악용 | 이미 공격 확인됨 | Confirmed | | CVSS 점수 | 발표되지 않음 (High 예상) | N/A |


단계별 대응 가이드

1단계: 현재 버전 확인

1
2
3
4
5
6
7
8
# Chrome 버전 확인 (Windows)
reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version

# Chrome 버전 확인 (macOS)
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version

# Chrome 버전 확인 (Linux)
google-chrome --version

2단계: 즉시 업데이트

1
2
3
4
5
graph LR
    A[크롬 메뉴] --> B[도움말]
    B --> C[Chrome 정보]
    C --> D[자동 업데이트 확인]
    D --> E[재시작]

안전한 버전 기준:

  • Chrome 131.0.6778.204 이상 (Windows, Mac)
  • Chrome 131.0.6778.204 이상 (Linux)

3단계: 엔터프라이즈 환경 대응

기업 환경에서는 그룹 정책 또는 MDM을 통한 강제 업데이트가 필요합니다.

1
2
3
4
5
6
7
8
// Chrome 정책 설정 예시 (policy.json)
{
  "Chrome": {
    "AutoUpdateCheckPeriodMinutes": 60,
    "UpdateDefault": 1,
    "TargetVersionPrefix": "131.0.6778"
  }
}

4단계: 완화 조치 (업데이트 불가 시)

즉시 업데이트가 어려운 환경에서는 다음과 같은 완화 조치를 적용합니다:

1
2
3
4
5
6
7
# Chromium Enterprise Policy
WebGpuBlockedForUrls:
  - "*"  # 모든 사이트에서 WebGPU 비활성화

# 또는 특정 도메인만 허용
WebGpuAllowedForUrls:
  - "trusted-internal.company.com"

Use-After-Free 방어 프로그래밍

개발자 관점에서 UAF 취약점을 예방하는 코딩 패턴을 살펴보겠습니다.

안전한 메모리 관리 패턴

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 안전한 스마트 포인터 사용 (Modern C++)
#include <memory>
#include <vector>

class GPUResource {
public:
    void process() { /* ... */ }
};

// 안전하지 않은 패턴
void unsafe_pattern() {
    GPUResource* ptr = new GPUResource();
    ptr->process();
    delete ptr;
    // ptr은 여전히 유효한 주소를 가리킴 (Dangling)
    // ptr->process();  // UAF 위험!
}

// 안전한 패턴
void safe_pattern() {
    auto ptr = std::make_unique<GPUResource>();
    ptr->process();
    // unique_ptr이 자동으로 관리, 해제 후 접근 불가
}

// 참조 카운팅을 통한 수명 관리
void shared_pattern() {
    auto ptr = std::make_shared<GPUResource>();
    auto weak_ref = std::weak_ptr<GPUResource>(ptr);
    
    // 안전한 접근
    if (auto locked = weak_ref.lock()) {
        locked->process();
    }
}

정적 분석 도구 활용

| 도구 | 용도 | 감지 능력 | | :— | :— | :— | | AddressSanitizer | 런타임 메모리 오류 | UAF, Buffer Overflow | | Clang Static Analyzer | 컴파일 타임 분석 | 잠재적 UAF | | Coverity | 정적 분석 | 다양한 메모리 버그 | | CodeQL | 시맨틱 분석 | 복잡한 UAF 패턴 |


브라우저 샌드박스와 익스플로잇

크롬 샌드박스 구조

1
2
3
4
5
6
7
8
graph TD
    A[Renderer Process] --> B[GPU Process]
    B --> C[Broker Process]
    C --> D[Kernel]
    
    A --> E[샌드박스 경계]
    E --> F[제한된 시스템 호출]
    F --> G[파일 시스템 격리]

샌드박스 탈출의 의미

CVE-2026-5281이 WebGPU/Dawn에서 발생한다는 것은 공격자가 GPU 프로세스에서 코드 실행 권한을 획득할 수 있음을 의미합니다. GPU 프로세스는 렌더러 프로세스보다 더 높은 권한을 가지며, 샌드박스 탈출의 발판이 될 수 있습니다.

공격 체인 예시: 1. 악성 웹페이지 → 렌더러 프로세스 (샌드박스 내) 2. WebGPU UAF 트리거 → GPU 프로세스 (약한 샌드박스) 3. GPU 드라이버 취약점 결합 → 커널 권한 획득


결론

핵심 요약

CVE-2026-5281은 이미 실제 공격에 악용된 제로데이 취약점으로, 크롬의 WebGPU 구현체 Dawn에서 발생한 Use-After-Free 버그입니다. 웹페이지 방문만으로도 임의 코드 실행이 가능하며, 샌드박스 탈출과 연계될 경우 시스템 전체 장악으로 이어질 수 있습니다.

즉시 조치 사항: 1. 모든 크롬 브라우저를 최신 버전으로 업데이트 2. 엔터프라이즈 환경에서는 강제 업데이트 정책 적용 3. WebGPU 사용이 불필요한 환경에서는 기능 비활성화 고려

전문가 인사이트

이번 사건은 웹 브라우저가 단순한 문서 뷰어를 넘어 저수준 하드웨어에 직접 접근하는 플랫폼으로 진화했음을 시사합니다. WebGPU, WebAssembly, WebNN 같은 새로운 웹 표준은 강력한 기능을 제공하지만, 동시에 새로운 공격 표면도 확장합니다.

특히 Use-After-Free 취약점은 C/C++ 기반 시스템에서 여전히 가장 빈번하게 발견되는 버그 유형입니다. Rust 같은 메모리 안전 언어의 도입이 근본적 해결책이 될 수


출처: https://news.hada.io/topic?id=28280

Hugo로 만듦
JimmyStack 테마 사용 중