
CVE-2023-32233의 재현 및 근본 원인 분석으로, 로컬 권한 상승을 가능하게 하는 Linux 커널 nf_tables use-after-free 취약점이며, PoC와 익스플로잇 노트를 포함합니다.
이 저장소는 무엇인가: 2023년 5월 Patryk Sondej와 Piotr Krysiuk에 의해 공개된, 로컬 권한 상승을 허용하는 Linux 커널 Netfilter nf_tables 서브시스템의 use-after-free 취약점인 CVE-2023-32233에 대한 직접 재현 및 연구입니다.
크레딧: PoC(exploit.c)와 원본 분석 글은 @Liuk3r의 것입니다. 이 저장소에서의 제 작업은 자체 랩 환경(Ubuntu 23.04, 커널 6.2.0-20)에서 익스플로잇을 재현하고 아래에 근본 원인과 익스플로잇 체인을 문서화하는 것입니다. 모든 테스트는 전용 랩 머신에서 수행되었습니다.
nf_tables는 구성 업데이트를 원자적 배치로 처리합니다. 동일한 배치 내 이전 작업들의 상태 변경에 대한 각 작업의 검증이 불충분합니다. 구체적으로:
nft_set에 대한 lookup 표현식을 포함하는 nft_rule로 시작합니다.NFT_MSG_DELRULE — 규칙을 삭제하며, 이는 암묵적으로 lookup 표현식과 익명 nft_set을 삭제합니다;NFT_MSG_DELSETELEM — 이미 삭제된 익명 set의 요소를 삭제합니다.nf_tables_commit_release()는 리소스를 nf_tables_destroy_list에 큐에 넣고, 이는 나중에 nf_tables_trans_destroy_work()에 의해 처리됩니다:
먼저 nft_commit_release() → nf_tables_rule_destroy() → nft_lookup_destroy() → nft_set_destroy() → kvfree()가 nft_set을 해제합니다;
그런 다음 NFT_MSG_DELSETELEM에 대해 nf_tables_set_elem_destroy()가 nft_set_elem_ext()를 호출하는데, 이는 해제된 nft_set을 역참조합니다:
set->ops->elemsize가 손상되면, 공격자가 선택한 메모리 위치가 nft_set_ext로 해석됩니다 — 나머지 모든 것이 이 위에 구축되는 프리미티브입니다.
nf_tables_trans_destroy_work()와의 레이스에서 승리: 제어된 지연으로 대규모 set-destroy 작업을 삽입하고, 다른 CPU들을 바쁘게 고정하고, 동일한 CPU에서 해제된 nft_set 청크를 다른 타입의 nft_set(다른 elemsize)으로 재할당 → 타입 혼동.nft_set_ext 헤더를 조작하여 nf_tables_set_elem_destroy()가 인접 청크를 파괴할 nft_expr의 리스트로 순회하도록 합니다.NFTA_LOG_PREFIX를 가진 nft_log 표현식을 스프레이; nft_log_destroy()가 priv->prefix를 해제하여 kmalloc-{8..192}에서 중첩 할당 프리미티브를 제공합니다(처음에는 NULL 바이트 제한).nft_object->udata로 재점유.특히, 선택된 프리미티브들은 CFI가 차단할 만한 것을 회피합니다 — 어느 단계에서도 간접 호출 하이재킹이 필요하지 않습니다.
SLAB_FREELIST_HARDENED), INIT_ON_FREE, 그리고 per-CPU slab 재사용 제한은 모두 1단계를 공격합니다; CFI(존재하는 경우)는 3단계 이상을 제약합니다.nf_tables 배치 netlink 메시지에 대한 감사 규칙; 스택에서 nft_set_elem_ext / nf_tables_trans_destroy_work에 대한 크래시 트리아지.nftables는 CAP_NET_ADMIN을 요구하지만, 비특권 사용자 네임스페이스가 이를 부여합니다 — 이것이 kernel.unprivileged_userns_clone=0이 의미 있는 강화 노브인 이유입니다.Ubuntu 23.04 (Lunar Lobster), 커널 6.2.0-20-generic에서 테스트되었습니다.
sudo apt install gcc libmnl-dev libnftnl-dev
gcc -Wall -o exploit exploit.c -lmnl -lnftnl
내장 프로파일은 Ubuntu 23.04 바이너리 커널(linux-image-6.2.0-20-generic 6.2.0-20.20)을 대상으로 합니다. 다른 커널을 테스트하려면 심볼을 profile 파일로 추출하세요:
modprobe nf_tables
egrep ' (nft_counter_ops|nft_counter_destroy|free_percpu|modprobe_path)(\s|$)' /proc/kallsyms > profile
nft_counter_destroy()의 기계어 레이아웃은 컴파일러와 옵션에 따라 달라집니다; 전체 매개변수 참조(nft_counter_destroy_call_offset/mask/check)와 레이스 튜닝 노브(race_lead_sleep 등)는 ORIGIN.md를 참조하세요. 보고된 성공 확률은 유휴 베어메탈 Intel 시스템에서 ≥80%입니다; 일부 마이크로아키텍처(예: Alder Lake)는 추가 튜닝이 필요합니다.
PoC는 성공적으로 실행된 후 커널을 손상된 메모리와 함께 불안정한 상태로 남깁니다. 전용 일회용 시스템이나 VM 스냅샷에서만 테스트하세요 — 소중한 데이터가 있는 곳에서는 절대 테스트하지 마세요.
exploit.c — PoC 소스 (@Liuk3r 작성)ORIGIN.md — 원본 취약점 및 익스플로잇 분석 글 (Liuk3r 작성)README.md — 이 파일: 재현 + 분석 노트격리된 랩 환경에서 방어/교육 목적으로 수행된 연구입니다.
static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
void *elem)
{
return elem + set->ops->elemsize;
}
nft_dynsetnft_counter — nft_counter_ops를 유출 → nf_tables.ko의 베이스(모듈에 대한 KASLR 무력화);nft_quota — consumed 포인터가 임의 읽기(NFT_MSG_GETSETELEM → nft_quota_do_dump() → NFTA_QUOTA_CONSUMED)와 임의 쓰기(루프백 트래픽에서 nft_overquota()가 skb->len을 *priv->consumed에 더함)를 제공.modprobe_path 덮어쓰기 ("/sbin/modprobe" → "//tmp/modprobe") → 공격자가 제어하는 내용으로 루트 프로세스 실행.