커널 보안 취약점 사례

대표적인 커널 보안 취약점 사례를 원인·악용 경로·완화 기법 관점에서 심층 분석합니다. Spectre/Meltdown 같은 마이크로아키텍처 취약점, Dirty COW 등 메모리 동기화 결함, 권한 상승·정보 유출 패턴의 공통 구조, 패치 전략과 회귀 위험, 배포판 백포트 시 주의점, 커널 설정 기반 완화 옵션의 성능 영향, 재현 실험과 포렌식 관찰 포인트까지 보안 대응 체계를 강화하기 위한 실무 지식을 다룹니다.

전제 조건: 동기화 기법메모리 배리어 문서를 먼저 읽으세요. 보안 취약점 분석은 동시성/수명주기 오류와 강하게 결합되므로, race/UAF 경로를 먼저 식별하는 관점이 필요합니다.
일상 비유: 이 주제는 시설 보안 점검과 침투 시뮬레이션과 비슷합니다. 출입 통제, 취약 구간, 경보 체계를 함께 점검하듯이, 커널 보안도 정책과 실행 경로를 동시에 검증해야 합니다.

핵심 요약

  • 전제 결합 — 보안, 성능, 아키텍처 지식을 함께 적용합니다.
  • 경계 명확화 — API 경계와 ABI 영향 범위를 먼저 확인합니다.
  • 위험 관리 — UAF, race, side-effect 가능성을 우선 점검합니다.
  • 계측 기반 판단 — 추측 대신 데이터로 개선 여부를 판단합니다.
  • 점진 적용 — 실험 범위를 작게 시작해 단계적으로 확장합니다.

단계별 이해

  1. 가설 수립
    문제와 개선 목표를 수치로 정의합니다.
  2. 제약 분석
    호환성, 안정성, 보안 제약을 먼저 확인합니다.
  3. 실험 적용
    최소 변경으로 효과와 부작용을 측정합니다.
  4. 정식 반영
    검증된 변경만 문서화해 반영합니다.
교육 목적 자료: 이 문서는 교육 목적으로 과거 보안 취약점을 분석합니다. 최신 커널에서는 대부분 패치되었습니다.
학습 방식: 본문은 개념 중심으로 설명하지만, 각 섹션에 운영 환경에서 바로 실행 가능한 점검 명령을 함께 배치했습니다. 배포판별 패치 포함 여부와 보안 정책 기본값은 참고자료 — FIPS 지원/인증 상태 및 벤더 보안 공지를 함께 확인하세요.

역사적 커널 보안 취약점 사례

리눅스 커널의 보안 취약점은 하드웨어 수준의 설계 결함부터 소프트웨어 논리 오류까지 다양한 형태로 발견되어 왔습니다. 주요 사례를 분석하고, 각 취약점이 커널 보안 아키텍처에 미친 영향과 완화 기법의 변천을 살펴봅니다.

Spectre 변종들과 완화 기법 변천사

2018년 1월 공개된 Spectre 취약점은 현대 프로세서의 투기적 실행(speculative execution) 메커니즘을 악용하여 커널 메모리를 읽어낼 수 있는 하드웨어 수준의 결함입니다. 커널은 소프트웨어 완화 기법을 통해 이 문제에 대응해 왔습니다.

Spectre v1 (CVE-2017-5753) — 배열 경계 검사 우회 (Bounds Check Bypass):

투기적 실행 중 배열 경계 검사가 우회되어, 공격자가 의도적으로 범위 밖 인덱스를 사용해 캐시 사이드채널을 통해 커널 메모리를 읽을 수 있습니다. 조건 분기가 아직 해결되지 않은 상태에서 프로세서가 경계 검사를 통과한 것으로 추측하고 실행을 진행하는 점을 악용합니다.

/* 취약한 코드 패턴 — Spectre v1에 노출 */
if (index < array_size) {
    value = array[index];           /* 투기적 실행 시 bounds check 우회 */
    leak  = probe_array[value * 4096]; /* 캐시 사이드채널 */
}

/* 완화된 코드 패턴 — array_index_nospec() 적용 */
#include <linux/nospec.h>

if (index < array_size) {
    index = array_index_nospec(index, array_size); /* 투기적 실행 시 인덱스를 0으로 클램프 */
    value = array[index];
}

array_index_nospec()는 조건 분기와 무관하게 인덱스를 안전 범위로 제한하는 데이터 의존성 기반 마스킹을 수행합니다. 투기적 실행 중에도 인덱스가 유효 범위를 벗어나지 않도록 보장합니다.

Spectre v2 (CVE-2017-5715) — 분기 예측 주입 (Branch Target Injection):

공격자가 간접 분기(indirect branch)의 예측 대상을 조작하여, 커널이 투기적으로 공격자가 선택한 가젯(gadget) 코드를 실행하게 만듭니다. 이를 통해 임의의 커널 메모리를 캐시 사이드채널로 유출할 수 있습니다.

/*
 * Retpoline: 간접 분기를 투기적 실행 불가능한 구조로 변환
 * GCC/Clang -mindirect-branch=thunk 옵션으로 자동 적용
 */

/* 일반 간접 호출 (취약) */
call *%rax                /* 분기 예측기가 대상을 조작 가능 */

/* Retpoline 변환 후 (완화) */
__x86_indirect_thunk_rax:
    call    retpoline_call_target
capture_ret:
    pause                    /* 투기적 실행이 여기서 무한 루프 */
    lfence
    jmp     capture_ret
retpoline_call_target:
    mov     %rax, (%rsp)     /* 실제 대상 주소를 리턴 스택에 배치 */
    ret                      /* ret로 간접 점프 → 분기 예측기 우회 */
하드웨어 완화 기법 (IBRS/IBPB/STIBP):

최신 프로세서는 마이크로코드 업데이트를 통해 하드웨어 수준의 완화를 제공합니다:

IBRS (Indirect Branch Restricted Speculation): 권한 수준이 변경될 때 간접 분기 예측을 제한합니다.
IBPB (Indirect Branch Prediction Barrier): 컨텍스트 전환 시 분기 예측 버퍼를 무효화합니다.
STIBP (Single Thread Indirect Branch Predictors): SMT(하이퍼스레딩) 환경에서 스레드 간 분기 예측 정보 공유를 차단합니다.
eIBRS (Enhanced IBRS)가 지원되는 경우, Retpoline 없이 하드웨어만으로 Spectre v2를 완화할 수 있습니다. /sys/devices/system/cpu/vulnerabilities/spectre_v2에서 현재 완화 상태를 확인할 수 있습니다.

/* 커널 내부 Spectre 완화 상태 확인 */
$ cat /sys/devices/system/cpu/vulnerabilities/spectre_v1
Mitigation: usercopy/swapgs barriers and __user pointer sanitization

$ cat /sys/devices/system/cpu/vulnerabilities/spectre_v2
Mitigation: Enhanced / Automatic IBRS; IBPB: conditional; STIBP: conditional; RSB filling; BHI: BHI_DIS_S

운영 환경 점검 체크리스트

점검 항목실행 명령판단 기준
CPU 완화 상태grep . /sys/devices/system/cpu/vulnerabilities/*Vulnerable가 남아있으면 즉시 원인 분석(마이크로코드/커널 파라미터/SMT 정책)
부트 파라미터cat /proc/cmdlinespectre_v2=off, mitigations=off 같은 완화 비활성 옵션 사용 금지
마이크로코드 반영dmesg | grep -i microcode부팅 시 마이크로코드 갱신 로그가 확인되어야 함
SMT 정책cat /sys/devices/system/cpu/smt/control위험 모델에 맞춰 on/off/forceoff를 명시적으로 운영

권한 상승 취약점 패턴 분석

커널 권한 상승(privilege escalation) 취약점은 일반 사용자가 root 권한을 획득할 수 있게 하는 가장 위험한 유형의 버그입니다. 파일시스템, 프로세스 관리, 메모리 관리 서브시스템의 경계에서 권한 검사가 누락되는 패턴이 반복적으로 발견됩니다.

CVE-2022-0492 — cgroup v1 release_agent 임의 명령 실행:

cgroup v1 환경에서 권한 검사가 미흡한 구성일 때 release_agent 파일에 임의 경로를 기록하면, cgroup 내 마지막 프로세스 종료 시 해당 경로의 바이너리가 호스트 root 권한으로 실행될 수 있습니다. 컨테이너 내부에서 cgroup 파일시스템 조작 조건이 충족되면 호스트 탈출과 권한 상승으로 이어질 수 있습니다.

/* CVE-2022-0492 공격 흐름 (개념적 설명) */

/* 1. 컨테이너 내부에서 cgroup v1 마운트 */
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp

/* 2. 자식 cgroup 생성 및 notify_on_release 활성화 */
mkdir /tmp/cgrp/child
echo 1 > /tmp/cgrp/child/notify_on_release

/* 3. release_agent에 호스트 경로의 악성 스크립트 지정 */
echo /path/to/malicious_script > /tmp/cgrp/release_agent

/* 4. child cgroup에서 프로세스 시작 후 즉시 종료 */
/* → release_agent가 호스트 root로 실행됨 */
sh -c "echo \$\$ > /tmp/cgrp/child/cgroup.procs"
CVE-2022-0847 (Dirty Pipe) — pipe 버퍼 플래그 오류로 임의 파일 쓰기:

Linux 5.8에서 도입된 버그로, pipe 버퍼의 PIPE_BUF_FLAG_CAN_MERGE 플래그가 새 pipe 버퍼 할당 시 초기화되지 않아 발생합니다. splice()로 파일 페이지 캐시를 pipe에 매핑한 뒤, 해당 pipe에 write()하면 페이지 캐시를 직접 덮어쓸 수 있습니다. 이를 통해 읽기 전용 파일(예: /etc/passwd, SUID 바이너리)을 임의로 수정하여 root 권한을 획득합니다.

/* Dirty Pipe (CVE-2022-0847) 핵심 메커니즘 */

/* copy_page_to_iter_pipe()에서 플래그 초기화 누락 */
static size_t copy_page_to_iter_pipe(struct page *page, ...) {
    struct pipe_buffer *buf = &pipe->bufs[i_head & p_mask];
    buf->ops   = &page_cache_pipe_buf_ops;
    buf->page  = page;
    buf->offset = offset;
    buf->len   = bytes;
    /* BUG: buf->flags 초기화 누락!
     * 이전 사용에서 PIPE_BUF_FLAG_CAN_MERGE가 남아있으면
     * 후속 write()가 페이지 캐시를 직접 덮어씀 */
}

/* 수정: flags를 명시적으로 초기화 */
buf->flags = 0;  /* 또는 적절한 초기값 설정 */
CVE-2023-0386 — OverlayFS + FUSE를 통한 setuid 바이너리 생성:

OverlayFS의 하위 레이어(lower layer)에 FUSE 파일시스템을 사용할 때, FUSE에서 setuid/setgid 비트가 설정된 파일을 제공하면 OverlayFS가 상위 레이어(upper layer)로 복사(copy-up)하는 과정에서 권한 검사가 누락됩니다. 일반 사용자가 user namespace 내에서 FUSE 마운트를 통해 root 소유의 setuid 바이너리를 생성하고, 이를 호스트에서 실행하여 권한을 상승시킬 수 있습니다.

권한 상승 취약점의 공통 패턴:

위 세 가지 취약점에서 반복되는 패턴은 파일시스템 계층 간 권한 검사 누락입니다:

- cgroup v1: cgroup 파일시스템 조작 → 호스트 명령 실행 (네임스페이스 경계 미검증)
- Dirty Pipe: pipe → 페이지 캐시 (버퍼 플래그 전파 시 초기화 누락)
- OverlayFS: FUSE → OverlayFS copy-up (레이어 간 setuid 비트 전파 시 권한 미검증)
커널 서브시스템 간 데이터가 이동할 때, 각 경계에서 권한과 무결성을 재검증해야 합니다.

권한 상승 취약점 전제 조건 비교

취약점주요 전제 조건탐지 단서
CVE-2022-0492cgroup v1 노출 + release_agent 조작 가능 + 네임스페이스 경계 검증 미흡/sys/fs/cgroup/*/release_agent 변경 이력, 비정상 cgroup 생성/삭제 급증
CVE-2022-0847취약 커널 + 공격자가 로컬 파일 쓰기 경로 확보읽기 전용 파일의 비정상 해시 변경, 감사 로그의 비정상 splice/write 패턴
CVE-2023-0386user namespace + OverlayFS copy-up + FUSE 조합 허용비정상 FUSE 마운트/overlay mount 시도, setuid 파일 생성 이벤트

Container Escape 취약점

컨테이너는 커널의 namespace, cgroup, seccomp 등으로 격리를 구현하지만, 커널 자체가 공유되므로 커널 취약점을 통한 탈출(escape)이 가능합니다. 컨테이너 보안의 근본적 한계와 주요 탈출 사례를 분석합니다.

CVE-2020-15257 — containerd shim API 접근으로 호스트 탈출:

containerd의 shim API가 abstract Unix domain socket으로 노출되어 있었으며, 호스트 네트워크 네임스페이스(--net=host)를 사용하는 컨테이너에서 이 소켓에 접근할 수 있었습니다. 공격자는 shim API를 통해 새로운 컨테이너를 호스트의 PID/mount 네임스페이스에서 실행시켜 호스트에 완전한 접근 권한을 획득합니다.

/* abstract Unix socket은 네트워크 네임스페이스에 바인딩됨 */
/* --net=host 컨테이너는 호스트의 abstract socket에 접근 가능 */

/* containerd shim이 abstract socket으로 API 노출 (취약) */
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
addr.sun_path[0] = '\0';  /* abstract namespace — 파일시스템에 없음 */
strncpy(&addr.sun_path[1], "/containerd-shim/...", ...);

/* 수정: filesystem-based socket으로 전환 → mount namespace로 격리 */
addr.sun_path[0] = '/';   /* 일반 경로 — mount namespace에 의해 격리됨 */
strncpy(addr.sun_path, "/run/containerd/shim/...", ...);
CVE-2022-0185 — fsconfig 힙 오버플로우를 통한 네임스페이스 탈출:

fsconfig() 시스템 콜에서 사용자 입력의 길이 검증이 부족하여 정수 언더플로우가 발생하고, 이로 인해 커널 힙에서 버퍼 오버플로우가 일어납니다. user namespace 내의 CAP_SYS_ADMIN 권한만으로도 트리거 가능하며, 힙 오버플로우를 통해 커널 자료구조를 덮어쓴 뒤 임의 코드 실행으로 초기 네임스페이스(init namespace)로 탈출할 수 있습니다.

/* CVE-2022-0185: legacy_parse_param()에서의 정수 언더플로우 */

static int legacy_parse_param(struct fs_context *fc,
                              struct fs_parameter *param) {
    ...
    size_t len = 0;

    /* 여러 파라미터를 연결하며 len 누적 */
    len += strlen(param->key);
    len += strlen(param->string);

    /* BUG: len이 PAGE_SIZE를 초과할 때 size 계산에서 언더플로우 발생 */
    size_t size = PAGE_SIZE - len;  /* 언더플로우 → 매우 큰 값 */

    /* 오버플로우된 size로 memcpy → 힙 오버플로우 */
    memcpy(buf + len, param->string, size);
    ...
}
Container Escape 방어 교훈:

컨테이너 탈출 취약점에 대한 핵심 방어 전략:

1. User Namespace 제한: 불필요한 경우 user.max_user_namespaces=0으로 비활성화하여 CVE-2022-0185와 같은 공격의 전제 조건을 제거합니다.
2. Seccomp 프로파일 강화: fsconfig, fsopen 등 컨테이너에서 불필요한 시스템 콜을 차단합니다. 기본 프로파일에 의존하지 말고 워크로드별 최소 허용 목록으로 공격 표면을 축소하세요.
3. 네트워크 격리 유지: --net=host 사용을 최소화하고, abstract Unix socket을 통한 호스트 서비스 노출을 점검합니다.
4. 커널 업데이트: 컨테이너 런타임과 커널을 최신 상태로 유지하는 것이 가장 기본적이면서 효과적인 방어입니다.

컨테이너 탈출 점검 명령 (실습)

# 1) user namespace 허용량 확인
sysctl user.max_user_namespaces

# 2) 컨테이너 런타임의 seccomp 적용 여부 확인 (예: Docker)
docker inspect --format '{{.HostConfig.SecurityOpt}} {{.HostConfig.Privileged}}' <container_id>

# 3) 호스트 네트워크 사용 컨테이너 탐지
docker ps --format '{{.ID}} {{.Names}} {{.Networks}}' | grep host

# 4) 최근 FUSE/overlay 관련 커널 로그 점검
dmesg | grep -Ei 'fuse|overlay|fsconfig|mount'

커널 정보 누출 (Information Leak) 패턴

커널 정보 누출은 커널 메모리의 내용이 사용자 공간으로 복사되어 KASLR 우회, 힙 스프레이 등 후속 공격에 활용되는 취약점 유형입니다. 초기화되지 않은 메모리가 사용자에게 전달되는 패턴이 가장 흔합니다.

초기화되지 않은 스택/힙 데이터 누출:

커널이 사용자 공간으로 데이터를 복사할 때, 구조체의 패딩 바이트나 사용되지 않는 필드가 초기화되지 않으면 이전 커널 스택/힙의 잔류 데이터가 그대로 사용자에게 전달됩니다. 이 데이터에는 커널 포인터(KASLR 우회), 다른 프로세스의 민감한 데이터, 커널 자료구조 주소 등이 포함될 수 있습니다.

/* 취약한 패턴: copy_to_user() 전 구조체 초기화 누락 */
struct user_info {
    __u32 type;      /* 4 bytes */
    __u64 value;     /* 8 bytes */
    /* 컴파일러가 type과 value 사이에 4바이트 패딩 삽입
     * 이 패딩은 초기화되지 않으면 커널 스택 데이터를 포함 */
};

long vulnerable_ioctl(struct file *f, unsigned int cmd, unsigned long arg) {
    struct user_info info;
    /* BUG: memset 누락! info의 패딩 바이트에 스택 잔류 데이터 존재 */
    info.type  = 1;
    info.value = get_some_value();
    /* 패딩 포함하여 16바이트 전체를 사용자 공간으로 복사 */
    if (copy_to_user((void __user *)arg, &info, sizeof(info)))
        return -EFAULT;
    return 0;
}

/* 수정된 패턴: memset()으로 전체 구조체 초기화 */
long safe_ioctl(struct file *f, unsigned int cmd, unsigned long arg) {
    struct user_info info;
    memset(&info, 0, sizeof(info));  /* 패딩 포함 전체 초기화 */
    info.type  = 1;
    info.value = get_some_value();
    if (copy_to_user((void __user *)arg, &info, sizeof(info)))
        return -EFAULT;
    return 0;
}
컴파일러 수준의 자동 초기화 방어:

수동 memset()은 누락되기 쉽기 때문에, 커널은 컴파일러 수준에서 자동으로 스택 변수를 초기화하는 옵션을 제공합니다:

CONFIG_INIT_STACK_ALL_ZERO: GCC 12+ / Clang 16+에서 -ftrivial-auto-var-init=zero 옵션을 사용하여 모든 스택 변수를 0으로 자동 초기화합니다. 성능 오버헤드는 1% 미만으로 보고되며, 정보 누출 취약점 클래스 전체를 체계적으로 제거합니다.
STRUCTLEAK GCC 플러그인: GCC 플러그인으로 사용자 공간에 복사되는 구조체를 감지하여 자동으로 0 초기화합니다. CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL이 가장 강력한 모드입니다.

/* CONFIG_INIT_STACK_ALL_ZERO 효과 */

/* 컴파일러가 함수 진입 시 모든 로컬 변수를 자동 초기화 */
long example_ioctl(struct file *f, unsigned int cmd, unsigned long arg) {
    struct user_info info;
    /* -ftrivial-auto-var-init=zero에 의해
     * info 전체(패딩 포함)가 자동으로 0 초기화됨
     * 별도의 memset() 없이도 정보 누출 방지 */
    info.type  = 1;
    info.value = get_some_value();
    if (copy_to_user((void __user *)arg, &info, sizeof(info)))
        return -EFAULT;
    return 0;
}

/* 커널 빌드 설정 */
/* .config에서 다음 옵션 활성화 */
CONFIG_INIT_STACK_ALL_ZERO=y          /* 스택 전체 0 초기화 */
CONFIG_GCC_PLUGIN_STRUCTLEAK=y        /* STRUCTLEAK 플러그인 (GCC 전용) */
CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y /* 모든 참조 전달 구조체 초기화 */
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y     /* 힙 할당 시 0 초기화 */

코드 리뷰 체크리스트 (Information Leak)

Dirty COW (CVE-2016-5195) — Copy-on-Write 경쟁 조건

2016년 10월 공개된 Dirty COW는 리눅스 커널 역사상 가장 널리 악용된 권한 상승 취약점 중 하나입니다. get_user_pages()의 Copy-on-Write 처리 과정에서 발생하는 경쟁 조건(race condition)을 악용하여, 읽기 전용 파일을 임의로 수정할 수 있습니다. 2007년(커널 2.6.22)부터 존재한 버그로, 약 9년간 커널에 잠복해 있었습니다.

CVE-2016-5195 (Dirty COW) — 핵심 메커니즘:

madvise(MADV_DONTNEED)/proc/self/mem에 대한 write()를 동시에 반복 호출하면, CoW 페이지 폴트 처리 경로에서 경쟁 조건이 발생합니다. follow_page_mask()가 CoW 복사본 대신 원본 읽기 전용 페이지에 대한 쓰기 참조를 반환하게 되어, 읽기 전용 파일(/etc/passwd, SUID 바이너리 등)을 직접 수정할 수 있습니다.

/* Dirty COW (CVE-2016-5195) 경쟁 조건 분석 */

/*
 * 정상 CoW 흐름:
 * 1. write fault → do_wp_page() → 새 페이지 할당 및 복사
 * 2. PTE를 새 페이지로 업데이트 (RW)
 * 3. 원본 페이지는 변경되지 않음
 *
 * 경쟁 조건 흐름:
 * Thread A: write(/proc/self/mem) → get_user_pages(FOLL_WRITE)
 *   → faultin_page() → CoW 복사 시작
 * Thread B: madvise(MADV_DONTNEED) → 방금 만든 CoW 복사본을 무효화
 *   → PTE를 다시 원본 읽기 전용 페이지로 되돌림
 * Thread A: follow_page_mask() 재시도 → FOLL_WRITE 제거 후
 *   → 원본 읽기 전용 페이지에 쓰기 참조 반환!
 */

/* mm/gup.c — 취약한 코드 (수정 전) */
static long __get_user_pages(..., unsigned int gup_flags, ...) {
retry:
    ...
    page = follow_page_mask(vma, start, foll_flags, &page_mask);
    if (!page) {
        ret = faultin_page(tsk, vma, start, foll_flags, &nonblocking);
        /* CoW 복사가 일어났지만, 다른 스레드가
         * madvise(MADV_DONTNEED)로 복사본을 폐기할 수 있음 */
        if (!ret)
            goto retry;
        /* retry 시 FOLL_WRITE가 빠져 원본 페이지에 접근 */
    }
}

/* 수정: FOLL_COW 플래그 도입 (commit 19be0eaffa3a) */
/* CoW 복사가 완료된 경우에만 쓰기 접근을 허용하고,
 * retry 시 CoW 상태를 재검증 */
Dirty COW의 교훈:

영향 범위: Linux 2.6.22 ~ 4.8.3 (2007~2016, 약 9년 잠복)
CVSS 점수: 7.8 (High) — 로컬 권한 상승
실제 악용: Android 루팅, 서버 침해에 광범위하게 사용됨
근본 원인: 멀티스레드 환경에서 메모리 관리 상태 변경과 접근 권한 검사 사이의 TOCTOU(Time-of-Check Time-of-Use) 문제
방어: 패치 커널(4.8.3+ 및 배포판 백포트) 적용, SUID/민감 경로 무결성 모니터링, 최소 권한 정책(LSM/seccomp)으로 익스플로잇 후 피해 범위 축소

하드웨어 투기적 실행 취약점 변형들

Spectre/Meltdown 이후 프로세서의 투기적 실행 관련 취약점이 지속적으로 발견되었습니다. 커널은 각 변형에 대해 소프트웨어 완화를 구현하고, /sys/devices/system/cpu/vulnerabilities/를 통해 시스템의 취약 여부와 완화 상태를 노출합니다.

투기적 실행 취약점 계보

투기적 실행 취약점 (2018~2024) Spectre 계열 (분기 예측) Spectre v1 — Bounds Check Spectre v2 — Branch Target Spectre v4 / SSB 2018 Spectre-BHB / BHI 2022 Retbleed 2022 SRSO / Inception 2023 Native BHI 2024 Meltdown 계열 (권한 우회) Meltdown / Rogue Data Load L1TF / Foreshadow 2018 iTLB Multihit 2018 마이크로아키텍처 버퍼 MDS (ZombieLoad/RIDL) 2018 TAA (TSX Async Abort) 2019 SRBDS / CrossTalk 2020 MMIO Stale Data 2022 GDS / Downfall 2022 RFDS (Atom 전용) 2023 기타 마이크로아키텍처 Zenbleed (AMD Zen 2) 2023 Reptar (Intel) 2023 GhostRace 2024
L1TF / Foreshadow (CVE-2018-3615, CVE-2018-3620, CVE-2018-3646):

L1 Terminal Fault는 Intel 프로세서에서 PTE(Page Table Entry)의 Present 비트가 0인 경우에도 L1 데이터 캐시에서 투기적으로 데이터를 읽을 수 있는 취약점입니다. SGX 엔클레이브, OS 커널, 가상 머신(VMX) 환경에 각각 영향을 미칩니다.

/* L1TF 완화 상태 확인 */
$ cat /sys/devices/system/cpu/vulnerabilities/l1tf
Mitigation: PTE Inversion; VMX: conditional cache flushes, SMT vulnerable

/*
 * L1TF 커널 완화 기법:
 *
 * 1. PTE Inversion: non-present PTE에서 물리 주소 비트를 반전시켜
 *    투기적 실행 시 L1 캐시 히트를 방지
 *    (arch/x86/include/asm/pgtable.h — protnone_mask())
 *
 * 2. VMX L1D Flush: VM 진입 전 L1 데이터 캐시를 플러시
 *    kvm_intel.vmentry_l1d_flush=always|cond|never
 *
 * 3. SMT 비활성화: HyperThread 형제 코어를 통한 L1D 공유 차단
 *    nosmt 또는 echo off > /sys/devices/system/cpu/smt/control
 */

/* 커널 부트 파라미터 */
l1tf=full        /* PTE inversion + VMX flush + SMT 비활성화 */
l1tf=full,force  /* 강제 적용 (사용자 변경 불가) */
l1tf=flush       /* PTE inversion + VMX flush (SMT 유지) */
l1tf=flush,nosmt /* flush + SMT 비활성화 */
l1tf=off         /* 완화 비활성화 (위험) */
MDS — Microarchitectural Data Sampling (CVE-2018-12126/12127/12130, CVE-2019-11091):

MDS는 Intel 프로세서의 내부 마이크로아키텍처 버퍼(Store Buffer, Fill Buffer, Load Port)에서 투기적 실행을 통해 데이터를 샘플링할 수 있는 취약점 계열입니다. RIDL(Rogue In-Flight Data Load), Fallout, ZombieLoad라는 이름으로도 알려져 있습니다.

/* MDS 취약점 변형들 */

/*
 * MSBDS (CVE-2018-12126) — Microarchitectural Store Buffer Data Sampling
 *   Store Buffer에 남은 이전 데이터를 투기적으로 읽기 (Fallout)
 *
 * MFBDS (CVE-2018-12130) — Microarchitectural Fill Buffer Data Sampling
 *   Fill Buffer의 데이터를 투기적으로 읽기 (ZombieLoad)
 *
 * MLPDS (CVE-2018-12127) — Microarchitectural Load Port Data Sampling
 *   Load Port에 남은 데이터를 투기적으로 읽기 (RIDL)
 *
 * MDSUM (CVE-2019-11091) — Microarchitectural Data Sampling Uncacheable Memory
 *   Uncacheable 메모리 접근 시 마이크로아키텍처 버퍼 데이터 누출
 */

/* MDS 완화 확인 */
$ cat /sys/devices/system/cpu/vulnerabilities/mds
Mitigation: Clear CPU buffers; SMT vulnerable

/*
 * 커널 완화: VERW 명령어를 사용한 CPU 버퍼 클리어
 * - 컨텍스트 전환 시 VERW 실행 → 내부 버퍼 덮어쓰기
 * - 커널→사용자 모드 전환 시 실행
 * - VM exit 시 실행
 * - idle 진입 시 실행
 *
 * 커널 부트 파라미터:
 * mds=full       — VERW 완화 + SMT 경고
 * mds=full,nosmt — VERW 완화 + SMT 비활성화
 * mds=off        — 완화 비활성화
 */

(투기적 실행 취약점 완화의 운영 관점은 커널 보안 — 커널 하드닝을 함께 참고하세요. 이 문서에서는 대표 취약점 패턴을 발췌해 설명합니다.)

Use-After-Free (UAF) 취약점 패턴

Use-After-Free는 리눅스 커널에서 가장 빈번하게 발견되는 메모리 안전성 취약점 유형입니다. 해제된 메모리 객체에 대한 참조가 남아있어, 해당 메모리가 재할당된 후 공격자가 제어하는 데이터로 덮어쓸 수 있습니다. 참조 카운트 관리 오류, 비동기 콜백의 생명주기 불일치, RCU 보호 누락 등이 근본 원인입니다.

nf_tables UAF (CVE-2024-1086) — Netfilter 권한 상승:

nf_tables의 verdict 처리에서 nft_verdict_init()NF_DROP에 긍정적 errno 값(예: NF_ACCEPT)을 허용하여, nf_hook_slow()에서 패킷이 Drop 대신 Accept로 처리됩니다. 이 과정에서 nft_do_chain()이 이미 해제된 skb에 대해 verdict를 수행하여 Use-After-Free가 발생합니다. CVSS 7.8, 로컬 권한 상승이 가능합니다.

UAF 취약점의 공통 패턴과 방어:

커널에서 UAF가 발생하는 주요 패턴과 각각의 방어 기법:

1. 참조 카운트 오류: kref, refcount_t의 put/get 불일치 → CONFIG_REFCOUNT_FULL로 underflow 감지
2. 비동기 콜백 생명주기: 타이머, workqueue, RCU 콜백이 소유 객체보다 오래 생존 → 해제 전 cancel_work_sync(), del_timer_sync() 필수
3. SLAB 재할당 공격: 해제된 slab 객체를 같은 크기의 공격자 제어 객체로 대체 → CONFIG_SLAB_FREELIST_HARDENED, CONFIG_RANDOM_KMALLOC_CACHES(6.6+)
4. RCU 보호 누락: RCU로 보호해야 할 포인터를 직접 해제 → kfree_rcu() 사용, rcu_dereference() 접근자 필수
탐지: KASAN(CONFIG_KASAN)이 UAF를 런타임에 감지. KFENCE(CONFIG_KFENCE)는 프로덕션 환경에서도 낮은 오버헤드로 UAF를 샘플링 탐지합니다.

UAF 의심 사고 초기 대응 절차

  1. 증거 보존
    dmesg, journalctl -k, 관련 코어 덤프를 먼저 보존하고 재부팅은 마지막에 수행합니다.
  2. 취약 경로 차단
    문제 서브시스템이 식별되면 관련 기능(예: 특정 netfilter rule update, ioctl 경로)을 임시 차단합니다.
  3. 탐지 강화
    재현 환경에서 KASAN/KFENCE를 활성화해 재발 경로를 수집합니다.
  4. 패치 우선순위
    해당 CVE 패치와 의존 패치를 묶어 적용하고, 동일 클래스(UAF) 관련 백포트 누락 여부를 함께 점검합니다.

Race Condition 취약점 패턴

커널의 동시성(concurrency) 처리에서 발생하는 경쟁 조건은 재현이 어렵고 탐지가 늦어지는 특성 때문에 장기간 잠복하는 경우가 많습니다. Dirty COW, 다수의 파일시스템/네트워크 스택 취약점이 이 패턴에 해당합니다.

CVE-2022-2588 — cls_route UAF (경쟁 조건):

네트워크 트래픽 분류기 route4에서 필터 삭제와 동시 접근 사이의 경쟁 조건으로 Use-After-Free가 발생합니다. 네임스페이스 내 CAP_NET_ADMIN 권한만으로 트리거 가능하며, 로컬 권한 상승이 가능합니다.

CVE-2023-3269 (StackRot) — Maple Tree RCU 경쟁 조건:

Linux 6.1에서 도입된 Maple Tree 자료구조의 VMA(Virtual Memory Area) 관리에서 RCU 보호와 mmap_lock 상호작용에 경쟁 조건이 존재합니다. Maple Tree 노드의 교체 과정에서 RCU 콜백이 아직 읽기 중인 노드를 해제하여 Use-After-Free가 발생합니다. 스택 기반의 공격(stack pivot)으로 권한 상승이 가능합니다.

/* Race Condition 취약점 탐지 도구 */

/* 1. KCSAN (Kernel Concurrency Sanitizer) — 동적 데이터 레이스 탐지 */
CONFIG_KCSAN=y
CONFIG_KCSAN_STRICT=y            /* 엄격 모드 */
CONFIG_KCSAN_REPORT_ONCE_IN_MS=0 /* 모든 레이스 보고 */

/* KCSAN이 탐지하는 패턴:
 * - 락 없는 공유 변수 동시 접근 (data race)
 * - READ_ONCE/WRITE_ONCE 누락
 * - 보호되지 않는 구조체 필드 접근
 */

/* 2. Lockdep — 잠금 의존성 및 데드락 사전 탐지 */
CONFIG_LOCKDEP=y
CONFIG_PROVE_LOCKING=y
CONFIG_LOCK_STAT=y

/* 3. syzbot/syzkaller — 퍼저 기반 경쟁 조건 탐지
 * Google이 운영하는 커널 퍼저로, 시스템 콜을 무작위 조합하여
 * 멀티스레드 시나리오에서 경쟁 조건을 자동 탐지
 * https://syzkaller.appspot.com — 발견된 버그 대시보드 */
커널 취약점 추적 리소스:

/sys/devices/system/cpu/vulnerabilities/ — 하드웨어 취약점 상태 및 완화 확인
https://www.cvedetails.com/vendor/33/Linux.html — Linux 커널 CVE 데이터베이스
https://syzkaller.appspot.com — syzbot 커널 퍼저 발견 버그 대시보드
https://git.kernel.org/pub/scm/linux/security/vulns.git/ — 커널 보안 취약점 공식 추적