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)

担当者が「受け入れる」か「破棄する」だけを選ぶ申請書を想像してください。別欄には破棄時のエラーコードを記入し、ゼロまたは有効な負のエラー値だけを許可します。脆弱な検証処理は、正の「受け入れる」値がその欄に入るのを許していました。その結果、後続のネットワーク処理で判定の解釈が食い違いました。修正では、正確に定義された判定値だけを受け入れます。

主要な概念と専門用語

nf_tables
nftablesがパケットフィルタリングなどのネットワークルールを設定するために使うLinuxカーネルのサブシステム。
Netfilter verdict
カーネルがパケットルールを評価した結果。例は NF_ACCEPT と NF_DROP です。DROPにはエラー値を付けられますが、hookはゼロまたは有効な負のerrnoを想定します。
解放後使用(CWE-416)
オブジェクトの寿命が終わった後にコードがそのメモリーへアクセスする欠陥です。NVDは本件をローカルのカーネル権限昇格として記録しています。
User namespace
プロセスのIDと権限を対応付けるLinux namespaceです。非特権ユーザーが作成できるかはカーネルとディストリビューションの方針によります。作成可能であることだけでホスト脱出が保証されるわけではありません。

フレームワーク対応

根本原因の分析 (Root Cause)

net/netfilter/nf_tables_api.c の nft_verdict_init() は、以前は判定値をマスクし、NF_DROP や NF_QUEUE のパラメーターを許可していました。Netfilter hook は NF_DROP の上位ビットにゼロまたは有効な負の errno が入ることを想定します。upstreamの修正によると、NF_ACCEPT のような正の値が解放後使用を引き起こす可能性がありました。パッチはこの寛容な経路を削除し、定義済みの判定値だけを許可します。それ以外は -EINVAL を返します。NVDは影響をローカル権限昇格としています。到達可能性はカーネル、利用可能な権限、ディストリビューションの方針によって異なり、すべてのコンテナーが同じ条件とは限りません。

ステップ・バイ・ステップの攻撃フロー

ステップ 1

ローカルでルールを管理できること

報告された攻撃はローカルから行われます。プロセスがnf_tablesの判定検証に到達できる必要があります。必要な権限や非特権user namespaceの可否はホスト設定によって異なります。

ステップ 2

無効な判定パラメーターが検証に到達

修正前の nft_verdict_init() は NF_VERDICT_MASK を適用した後、一部のパラメーター付き値を許可していました。パラメーター部分に正の NF_ACCEPT が含まれる場合も該当します。

ステップ 3

hook処理で解放後使用が発生

Netfilter hookは NF_DROP のパラメーターをゼロまたは有効な負のerrnoとして解釈します。upstreamの報告は、許可された正の値がパケット処理中に解放後使用を引き起こし得ると説明しています。一般化できる攻撃プリミティブや、必ずコンテナーから脱出できることを示すものではありません。

ステップ 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;
}

エンジニアリング&システム堅牢化チェックリスト

参考資料