FlawOpen

flawopen.com/Teardowns/cve-2024-1086-linux-netfilter-nftables-uaf

● CVE-2024-1086 · CVSS 7.8 · 높음
보안 연구 · FlawOpen

CVE-2024-1086: Linux nf_tables 해제 후 사용

CVE-2024-1086은 잘못된 DROP 매개변수를 허용한 Linux nf_tables의 해제 후 사용 취약점입니다. 배포판의 수정 커널을 설치하세요.

💡 알기 쉬운 설명 (ELI5)

담당자가 “허용” 또는 “거부”만 선택할 수 있는 양식을 떠올려 보세요. 별도 칸에는 거부 오류 코드를 적으며, 0이나 유효한 음수 오류 값만 허용됩니다. 취약한 검증 코드는 양수인 “허용” 값이 그 칸에 들어가는 것을 막지 못했습니다. 이후 네트워크 코드가 같은 판정을 서로 다르게 해석했습니다. 패치는 정확히 지원되는 판정 값만 받아 이 경로를 닫습니다.

핵심 개념 및 용어

nf_tables
nftables가 패킷 필터링과 관련 네트워크 규칙을 설정할 때 사용하는 Linux 커널 하위 시스템입니다.
Netfilter 판정
커널이 패킷 규칙을 평가한 결과이며 NF_ACCEPT나 NF_DROP 등이 있습니다. DROP에는 오류 값이 포함될 수 있고 hook은 0 또는 유효한 음수 errno를 예상합니다.
해제 후 사용 (CWE-416)
객체의 수명이 끝난 뒤에도 코드가 해당 메모리에 접근하는 메모리 안전 결함입니다. NVD는 이 문제를 로컬 커널 권한 상승으로 기록합니다.
User namespace
프로세스의 ID와 capability를 매핑하는 Linux namespace입니다. 비특권 사용자의 생성 가능 여부는 커널 및 배포판 정책에 따라 다르며, 이것만으로 호스트 탈출이 보장되지는 않습니다.

프레임워크 매핑

근본 원인 분석 (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, 배포판 정책에 따라 다르므로 모든 컨테이너가 같은 조건이라고 단정하지 마세요.

단계별 공격 실행 흐름

단계 1

로컬 규칙 관리 권한

문서화된 공격은 로컬 공격입니다. 프로세스가 nf_tables 판정 검증 경로에 도달할 수 있어야 하며, 필요한 권한과 비특권 user namespace 허용 여부는 호스트 설정에 달려 있습니다.

단계 2

잘못된 판정 매개변수가 검증에 도달

수정 전 nft_verdict_init()는 NF_VERDICT_MASK를 적용한 뒤 일부 매개변수 값을 허용했습니다. 매개변수 비트에 양수 NF_ACCEPT가 포함되는 경우도 있었습니다.

단계 3

hook 처리에서 해제 후 사용

Netfilter hook은 NF_DROP 매개변수를 0 또는 유효한 음수 errno로 해석합니다. upstream 보고는 허용된 양수 값이 패킷 처리 중 해제 후 사용을 일으킬 수 있다고 설명합니다. 이 패치는 보편적인 exploit primitive나 보장된 컨테이너 탈출을 입증하지 않습니다.

단계 4

배포판의 수정 커널 설치

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;
}

엔지니어링 및 시스템 보안 강화 체크리스트

출처