flawopen.com/Teardowns/cve-2024-1086-linux-netfilter-nftables-uaf
CVE-2024-1086: Linux nf_tables 해제 후 사용
CVE-2024-1086은 잘못된 DROP 매개변수를 허용한 Linux nf_tables의 해제 후 사용 취약점입니다. 배포판의 수정 커널을 설치하세요.
담당자가 “허용” 또는 “거부”만 선택할 수 있는 양식을 떠올려 보세요. 별도 칸에는 거부 오류 코드를 적으며, 0이나 유효한 음수 오류 값만 허용됩니다. 취약한 검증 코드는 양수인 “허용” 값이 그 칸에 들어가는 것을 막지 못했습니다. 이후 네트워크 코드가 같은 판정을 서로 다르게 해석했습니다. 패치는 정확히 지원되는 판정 값만 받아 이 경로를 닫습니다.
핵심 개념 및 용어
nf_tables- nftables가 패킷 필터링과 관련 네트워크 규칙을 설정할 때 사용하는 Linux 커널 하위 시스템입니다.
Netfilter 판정- 커널이 패킷 규칙을 평가한 결과이며
NF_ACCEPT나NF_DROP등이 있습니다. DROP에는 오류 값이 포함될 수 있고 hook은 0 또는 유효한 음수 errno를 예상합니다. 해제 후 사용 (CWE-416)- 객체의 수명이 끝난 뒤에도 코드가 해당 메모리에 접근하는 메모리 안전 결함입니다. NVD는 이 문제를 로컬 커널 권한 상승으로 기록합니다.
User namespace- 프로세스의 ID와 capability를 매핑하는 Linux namespace입니다. 비특권 사용자의 생성 가능 여부는 커널 및 배포판 정책에 따라 다르며, 이것만으로 호스트 탈출이 보장되지는 않습니다.
프레임워크 매핑
- 이 가이드에서 설명하는 약점의 CWE 참조: CWE-416
- CISA KEV — 추가일 2024-05-30 — CVE-2024-1086
근본 원인 분석 (Root Cause)
net/netfilter/nf_tables_api.c의 nft_verdict_init()는 이전에 판정 값을 마스킹해 NF_DROP 또는 NF_QUEUE의 매개변수를 허용했습니다. Netfilter hook은 NF_DROP의 상위 비트가 0 또는 유효한 음수 errno라고 가정합니다. upstream 수정 설명에 따르면 NF_ACCEPT 같은 양수 값이 해제 후 사용을 일으킬 수 있었습니다. 패치는 허용적인 경로를 제거하고 정확히 지원되는 판정만 받으며, 나머지는 -EINVAL을 반환합니다. NVD는 영향을 로컬 권한 상승으로 기록합니다. 도달 가능성은 커널, 사용 가능한 capability, 배포판 정책에 따라 다르므로 모든 컨테이너가 같은 조건이라고 단정하지 마세요.
단계별 공격 실행 흐름
로컬 규칙 관리 권한
문서화된 공격은 로컬 공격입니다. 프로세스가 nf_tables 판정 검증 경로에 도달할 수 있어야 하며, 필요한 권한과 비특권 user namespace 허용 여부는 호스트 설정에 달려 있습니다.
잘못된 판정 매개변수가 검증에 도달
수정 전 nft_verdict_init()는 NF_VERDICT_MASK를 적용한 뒤 일부 매개변수 값을 허용했습니다. 매개변수 비트에 양수 NF_ACCEPT가 포함되는 경우도 있었습니다.
hook 처리에서 해제 후 사용
Netfilter hook은 NF_DROP 매개변수를 0 또는 유효한 음수 errno로 해석합니다. upstream 보고는 허용된 양수 값이 패킷 처리 중 해제 후 사용을 일으킬 수 있다고 설명합니다. 이 패치는 보편적인 exploit primitive나 보장된 컨테이너 탈출을 입증하지 않습니다.
배포판의 수정 커널 설치
upstream 변경은 지원되지 않는 판정 매개변수를 거부합니다. 패키지 버전과 백포트는 다르므로 배포판이 제공한 수정 커널을 설치하고 부팅하세요.
소스 코드 비교: 취약한 구현 vs 보안 패치
취약한 코드는 판정 값을 마스킹한 뒤 계속 처리해 양수 NF_ACCEPT 같은 값이 NF_DROP의 오류 필드에 들어갈 수 있었습니다. 수정 코드는 정확한 상수만 허용하고 다른 값에는 -EINVAL을 반환합니다. 아래는 upstream 패치의 핵심 발췌이며 독립적으로 컴파일 가능한 완전한 함수는 아닙니다.
소스 코드 발췌: net/netfilter/nf_tables_api.c
/* f342de4e2f33 이전 net/netfilter/nf_tables_api.c의 nft_verdict_init() 일부입니다.
* 마스크 값 경로가 매개변수화된 verdict를 허용했습니다. */
switch (data->verdict.code) {
default:
switch (data->verdict.code & NF_VERDICT_MASK) {
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
break;
default:
return -EINVAL;
}
fallthrough;
case NFT_CONTINUE:
case NFT_BREAK:
case NFT_RETURN:
/* 나머지 기존 verdict 처리는 이어집니다. */
break;
}
/* f342de4e2f33에서 변경된 net/netfilter/nf_tables_api.c의
* nft_verdict_init() 일부입니다. */
switch (data->verdict.code) {
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
break;
case NFT_CONTINUE:
case NFT_BREAK:
case NFT_RETURN:
/* 나머지 기존 verdict 처리는 이어집니다. */
break;
default:
return -EINVAL;
}
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓배포판이 권장하는 수정 커널 패키지를 설치하고 부팅한 뒤, 재시작 후 실행 중인 커널을 확인하세요. 백포트에 따라 버전 번호가 다를 수 있습니다.
- ✓단일 upstream 버전 비교에 의존하지 말고 사용 중인 커널 종류와 패키지에 대한 배포판 보안 공지를 확인하세요.
- ✓업데이트를 미뤄야 한다면 비특권 user namespace 생성을 제한하는 공급업체 문서의 방법을 검토하세요. 해당 배포판에서 지원되는지 확인하고 컨테이너 및 데스크톱 앱 영향을 시험하세요.
- ✓커널 판정 검증을 검토할 때 지원되지 않는 매개변수 비트를 packet hook 경로 전에 거부하고, 허용 상수와 잘못된 양수 값을 테스트하세요.