
Linux 관련 취약점
이 저장소의 목적: CVE-2023-32233의 직접 재현 및 연구입니다. 이는 로컬 권한 상승을 허용하는 Linux 커널 Netfilter nf_tables 서브시스템의 use-after-free 취약점으로, 2023년 5월 Patryk Sondej와 Piotr Krysiuk에 의해 공개적으로 발표되었습니다.
크레딧: PoC(exploit.c)와 원본 분석 글은 @Liuk3r의 것입니다. 이 저장소에서 제 작업은 자체 랩(Ubuntu 23.04, 커널 6.2.0-20)에서 익스플로잇을 재현하고 아래에 근본 원인과 익스플로잇 체인을 문서화하는 것입니다. 모든 테스트는 전용 랩 머신에서 수행되었습니다.
nf_tables는 구성 업데이트를 원자적 배치(atomic batch)로 처리합니다. 동일한 배치 내 이전 작업의 상태 변경에 대한 각 작업의 검증이 불충분합니다. 구체적으로:
nft_set에 lookup 표현식이 포함된 nft_rule로 시작합니다.NFT_MSG_DELRULE — 규칙을 삭제하며, lookup 표현식과 익명 nft_set을 암시적으로 삭제합니다;NFT_MSG_DELSETELEM — 이미 삭제된 익명 셋의 요소를 삭제합니다.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()를 상대로 레이스를 이깁니다: 제어된 지연으로 대규모 셋-파괴 작업을 삽입하고, 다른 CPU를 바쁘게 유지하며, 해제된 nft_set 청크를 동일 CPU에서 다른 유형(다른 elemsize)의 nft_set으로 재할당합니다 → 타입 혼동(type confusion).nft_set_ext 헤더 제작: 범위를 벗어난 오프셋을 사용하여 nf_tables_set_elem_destroy()가 인접 청크를 파괴할 nft_expr 목록처럼 순회하도록 만듭니다.nft_log 표현식 스프레이: 제어된 NFTA_LOG_PREFIX로 스프레이합니다; nft_log_destroy()는 priv->prefix를 해제하여 kmalloc-{8..192}에서 중첩 할당(overlapping allocation) 프리미티브를 제공합니다(처음에는 NULL-바이트 제한이 있음).nft_object->udata로 재확보: dangling read에 대한 NULL-바이트 제한을 해제합니다.특히, 선택된 프리미티브는 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_dynset 요소 스프레이nft_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") → 공격자가 제어하는 콘텐츠로 루트 프로세스 실행.