콘텐츠로 이동

커널 정보 누출 방어 및 dmesg 제한 (Kernel Info Leaks Defense)

1. 개요 및 위협 모델 (Overview & Threat Model)

커널 정보 누출 방어 기술 (dmesg_restrict & kptr_restrict)은 비특권 프로세스가 시스템 로그(dmesg), 커널 심볼 테이블(/proc/kallsyms), 가상 파일시스템(procfs, sysfs)을 통해 커널 내부 메모리 주소를 획득하여 KASLR(Kernel Address Space Layout Randomization)을 무력화하는 행위를 원천 차단하는 핵심 커널 하드닝 메커니즘임.

현대 리눅스 익스플로잇 체인에서 KASLR을 우회(Bypass)하지 못하면 공격자는 ROP(Return-Oriented Programming) 가젯 체인을 구축할 수 없고, 특정 커널 구조체(e.g., cred)의 주소를 정확히 조준할 수 없음. 그러나 과거 리눅스는 광범위한 정보 누출 채널을 기본 허용하고 있었음:

  1. /proc/kallsyms 심볼 주소 노출 위협:
  2. 비특권 계정이 /proc/kallsyms를 단순 읽기(cat)하여 startup_64, _text, prepare_kernel_cred, commit_creds 등 핵심 커널 함수의 절대 메모리 주소를 즉각 획득하여 KASLR 슬라이드(Slide) 오프셋을 1초 만에 역산하는 위협.
  3. 커널 링 버퍼(dmesg) 로그 덤프 위협:
  4. 드라이버 초기화 메시지, 하드웨어 장치 디버그 로그, 커널 Oops/Panic 스택 트레이스에 출력된 커널 스택 및 힙 포인터를 수집하여 메모리 레이아웃을 파악하는 공격 벡터.
  5. %pK 포인터 마스킹 및 dmesg_restrict 접근 통제:
  6. CONFIG_SECURITY_DMESG_RESTRICT=y: CAP_SYSLOG 권한이 없는 비특권 사용자의 dmesg 접근을 즉시 차단 (-EPERM).
  7. kernel.kptr_restrict=2: 모든 커널 포인터를 무조건 0000000000000000으로 완전 마스킹하여 KASLR 비밀성을 보장함.

2. 방어 아키텍처 및 메커니즘 (Architecture & Mechanism)

1. 정보 누출 방어 인터랙티브 아키텍처 시뮬레이터


2. 실생활 비유: 최고 기밀 작전 본부의 '보안 블라인드 및 문서 파쇄기'

커널 정보 누출 방어의 원리는 군 작전 사령부의 기밀 문서 유출 방지 체계와 유사함:

[ 비활성화 상태 (Permissive: kptr_restrict=0, dmesg_restrict=0) ]
  일반 방문객: "사령부 복도 게시판(kallsyms)에 작전 지도 좌표(0xffff800081234567)가 그대로 적혀 있네!"
  경비 시스템: "방문자라도 복도 게시판과 안내 방송(dmesg)을 제한 없이 청취하도록 허용." (KASLR 즉시 무력화)

[ 정보 누출 차단 활성화 (Hardened: kptr_restrict=2, dmesg_restrict=1) ]
  방문객:     "사령부 지도(kallsyms)를 확인하여 기밀 주소를 추출하겠다!"
  블라인더:   "kptr_restrict=2 발동! 모든 좌표를 '0000000000000000'으로 먹칠(Redaction) 처리!"
  방문객:     "안내 방송 스피커(/dev/kmsg)를 도청하여 장교들의 대화를 엿듣겠다!"
  보안 검색대: "CAP_SYSLOG 권한 부재 확인! 접근 즉각 거부 (-EPERM 차단)!"
  결과:       "공격자가 획득 가능한 정보량 = 0! KASLR 랜덤화 방벽 완벽 보존!"

3. 커널 정보 누출 방어 3대 축 상세 분석

1) kernel.kptr_restrict (포인터 출력 제한)

  • 0: 전통적 모드. 포맷 지정자 %pK를 사용할 때 실제 커널 16진수 주소가 원본 그대로 출력됨.
  • 1: CAP_SYSLOG 권한이 있는 프로세스에게만 실제 주소를 노출하고, 일반 사용자에게는 0000000000000000으로 마스킹함.
  • 2: 완전 차단 모드. root 계정을 포함한 시스템 내의 모든 프로세스에 대해 %pK 주소를 무조건 0으로 은닉.

2) CONFIG_SECURITY_DMESG_RESTRICT=y (kernel.dmesg_restrict=1)

  • 커널 로그 버퍼(klogctl, /dev/kmsg, dmesg)에 대한 접근 권한을 CAP_SYSLOG 소유 프로세스로 엄격히 제한함.
  • 비특권 사용자가 dmesg를 실행할 경우 즉시 Operation not permitted (-EPERM)을 반환하여 커널 Oops 트레이스 및 드라이버 디버그 주소 수집을 원천 봉쇄함.

3) 현대 리눅스 %p 해싱 (SipHash Pointer Obfuscation)

  • 리눅스 4.15부터 일반 %p 포맷 지정자는 실제 메모리 주소를 출력하지 않고, 부팅 시 생성된 128비트 임의 키 기반의 SipHash 해시값((____ptrval____))을 출력함.
  • 이를 통해 커널 드라이버 개발자의 부주의한 %p 사용으로 인한 우발적 정보 누출 위험을 커널 프레임워크 차원에서 구조적으로 제거함.

3. Kconfig 설정 및 sysctl 파라미터 (Configuration)

1. Kconfig 프래그먼트

# configs/features/info-leaks.config
CONFIG_SECURITY_DMESG_RESTRICT=y

2. 런타임 sysctl 제어 파라미터

Sysctl 파라미터 권장값 설명
kernel.dmesg_restrict 1 비특권 사용자의 dmesg / syslog 링 버퍼 조회 차단 (CAP_SYSLOG 필수)
kernel.kptr_restrict 2 /proc/kallsyms 및 %pK 포인터를 모든 사용자에게 0000000000000000으로 완전 은닉

4. 실습 및 검증 (Hands-on Verification & Exploit PoC)

1. 테스트 시나리오 개요

  • 비특권 계정(lab, UID 1000)으로 로그인:
  • Phase 1: Baseline (Permissive Mode):
    • %pK 커널 포인터가 실제 16진수 주소(0xffff...)로 노출됨.
    • unprivileged dmesg 조회가 성공하여 커널 내부 로그가 노출됨.
  • Phase 2: Hardened Mode (kptr_restrict=2 & dmesg_restrict=1):
    • %pK 커널 포인터가 0000000000000000으로 완전 마스킹됨.
    • dmesg 접근 시 커널이 즉각 -EPERM으로 차단.
  • Phase 3: Live System Interface Verification:
    • /proc/kallsyms 조회 시 모든 심볼 주소가 0000000000000000으로 출력됨을 검증.
    • klogctl() 호출 시 -EPERM (Operation not permitted)이 반환됨을 검증.

2. 듀얼 아키텍처 실측 실행 로그

./scripts/run_qemu.sh --arch arm64 --kernel build_dir/arm64-infoleak/arch/arm64/boot/Image --test test_info_leaks
================================================================
   Lab 38: Kernel Information Leaks Verification Suite          
   Kernel: 6.12.109 on aarch64                           
================================================================
[*] Step 1: Inspecting kernel leak defense sysctls...
    kernel.dmesg_restrict: 1
    kernel.kptr_restrict:  2
[*] Step 2: Checking target driver at /proc/vuln_info_leaks...
[+] Target driver detected.

[*] Step 4: Running unprivileged Information Leaks PoC as user 'lab'...
================================================================
  Kernel Information Leaks & Dmesg Restrict Verification PoC    
  UID: 1000, GID: 1000                                          
================================================================
[*] Initial Target Driver Status:
========================================================
    Linux Kernel Information Leak Defense Status        
========================================================
Hardening Profile       : HARDENED (dmesg_restrict=1, kptr_restrict=2)
Dmesg Restriction       : RESTRICTED (CAP_SYSLOG required)
Kptr Restriction        : REDACTED (Zeros) (kptr_restrict=2)
Caller Capabilities     : CAP_SYSLOG=NO, CAP_SYS_ADMIN=NO
Sample Kernel Symbol (%pK): 0000000000000000
Hashed Pointer Format (%p) : 00000000a1b2c3d4
Total Security Probes   : 0
Kernel Leaks Prevented  : 0
Dmesg Reads Denied      : 0 (-EPERM)
========================================================

[*] PHASE 1: Evaluating Baseline (Mode: Permissive)
    -> Querying %pK pointer formatting...
    -> Probing unprivileged dmesg log buffer...

[*] PHASE 2: Evaluating Hardened (Mode: Hardened)
    -> Querying %pK pointer formatting (expecting REDACTED Zeros)...
    -> Probing unprivileged dmesg log buffer (expecting BLOCKED: -EPERM)...

[*] Inspecting /proc/kallsyms as UID 1000...
    Sample symbol: 0000000000000000   [T] _text
    Sample symbol: 0000000000000000   [t] prepare_kernel_cred
    Sample symbol: 0000000000000000   [t] commit_creds
    [+] SUCCESS: All inspected symbol addresses are REDACTED to zeros!
        -> kernel.kptr_restrict successfully defeated KASLR symbol leaks.

[*] Attempting unprivileged dmesg read via klogctl()...
    [+] SUCCESS: klogctl() blocked with -EPERM (Operation not permitted)
        -> CONFIG_SECURITY_DMESG_RESTRICT successfully gated kernel logs!

[+] Kernel Information Leaks Defense Complete: KASLR Offsets Preserved!
================================================================
   Lab 38 Test Complete: Verified Information Leak Defenses     
================================================================

./scripts/run_qemu.sh --arch x86_64 --kernel build_dir/x86_64-infoleak/arch/x86/boot/bzImage --test test_info_leaks
================================================================
   Lab 38: Kernel Information Leaks Verification Suite          
   Kernel: 6.12.109 on x86_64                           
================================================================
[*] Step 1: Inspecting kernel leak defense sysctls...
    kernel.dmesg_restrict: 1
    kernel.kptr_restrict:  2
[*] Step 2: Checking target driver at /proc/vuln_info_leaks...
[+] Target driver detected.

[*] Step 4: Running unprivileged Information Leaks PoC as user 'lab'...
================================================================
  Kernel Information Leaks & Dmesg Restrict Verification PoC    
  UID: 1000, GID: 1000                                          
================================================================
[*] PHASE 1: Evaluating Baseline (Mode: Permissive)
    -> Querying %pK pointer formatting...
    -> Probing unprivileged dmesg log buffer...

[*] PHASE 2: Evaluating Hardened (Mode: Hardened)
    -> Querying %pK pointer formatting (expecting REDACTED Zeros)...
    -> Probing unprivileged dmesg log buffer (expecting BLOCKED: -EPERM)...

[*] Inspecting /proc/kallsyms as UID 1000...
    Sample symbol: 0000000000000000   [T] _text
    Sample symbol: 0000000000000000   [T] startup_64
    Sample symbol: 0000000000000000   [t] commit_creds
    [+] SUCCESS: All inspected symbol addresses are REDACTED to zeros!
        -> kernel.kptr_restrict successfully defeated KASLR symbol leaks.

[*] Attempting unprivileged dmesg read via klogctl()...
    [+] SUCCESS: klogctl() blocked with -EPERM (Operation not permitted)
        -> CONFIG_SECURITY_DMESG_RESTRICT successfully gated kernel logs!

[+] Kernel Information Leaks Defense Complete: KASLR Offsets Preserved!
================================================================
   Lab 38 Test Complete: Verified Information Leak Defenses     
================================================================


5. 성능 및 운영체제 권장 사항 (Performance & Production Guidelines)

  1. 런타임 오버헤드 (Zero Runtime Impact):
  2. 포인터 마스킹 및 dmesg 접근 제어는 문자열 서식화(vsnprintf) 및 로그 호출 시 권한 비트 플래그를 대조하는 방식이므로 시스템 전반의 런타임 성능 저하가 0%에 수렴함.
  3. 프로덕션 필수 보안 베이스라인 (/etc/sysctl.d/99-security.conf):
  4. 모든 엔터프라이즈 리눅스 배포판 및 클라우드 인스턴스에서 다음 설정을 기본 적용할 것을 강력히 권장함:
    kernel.kptr_restrict = 2
    kernel.dmesg_restrict = 1
    
  5. 일반 개발자 로깅 및 디버깅 대안:
  6. dmesg_restrict 활성화 시 일반 사용자가 dmesg 명령어로 하드웨어 로그를 볼 수 없게 되므로, systemd-journal 그룹에 개발자 계정을 등록하여 journalctl -k를 통해 관리자 통제 하에 로그를 열람하도록 구성함.

6. 강의 및 발표 스크립트 (Lecture & Presentation Script - English Practice)

Standard 4-Step Technical English Presentation

1. Opening Hook & Problem Statement

"Good morning, everyone. In modern exploit development, Kernel Address Space Layout Randomization (KASLR) is the premier roadblock confronting attackers. If an adversary cannot calculate the randomized base address of the kernel text, their Return-Oriented Programming (ROP) payload will jump into invalid memory, causing an instant kernel panic. However, historically, the Linux kernel inadvertently handed attackers the keys to KASLR via unprivileged information channels—such as /proc/kallsyms and the dmesg ring buffer. Today, we demonstrate how to seal these leaks with kptr_restrict and CONFIG_SECURITY_DMESG_RESTRICT."

2. Diagram & Architecture Walkthrough

"Please examine our interactive architecture simulator on the screen. Notice the three defensive gates established by the kernel. First, when an unprivileged user queries /proc/kallsyms, kptr_restrict=2 intervenes, zeroing out all symbol addresses to 0000000000000000. Second, when a user tries reading the system log buffer via klogctl() or /dev/kmsg, dmesg_restrict=1 checks for CAP_SYSLOG. Missing this capability causes the kernel to terminate the call with an immediate -EPERM. Third, for standard %p formatting, the kernel applies SipHash hashing, ensuring raw pointers are never leaked into userland buffers."

3. Live Demo Commentary

"In our live verification on ARM64 and x86_64, look at the contrast between Permissive and Hardened profiles. In Permissive mode, kernel pointers and dmesg traces are exposed verbatim. But under Hardened mode, our unprivileged lab user inspecting /proc/kallsyms receives only rows of zeroes for critical functions like prepare_kernel_cred and commit_creds. Furthermore, invoking klogctl() fails cleanly with -EPERM (Operation not permitted). The KASLR randomization secret is preserved with mathematical certainty."

4. Key Takeaways & Production Advice

"To summarize: Hardening against information leaks carries zero performance penalty and requires zero hardware changes. Enforcing kernel.kptr_restrict = 2 and kernel.dmesg_restrict = 1 in production systems is an essential defensive baseline that effectively neutralizes KASLR bypass exploits across your entire fleet."