```
██╗ ██╗██████╗
██║ ██║██╔══██╗
██║ ██║██║ ██║
██║ ██║██║ ██║
███████╗██║██████╔╝
╚══════╝╚═╝╚═════╝
```
— 「Linuxは死にかけている」 —
LSMのセキュリティ保証を迂回するカーネルコードパスの体系的な発見
門は破られたのではない。迂回されたのだ。
Linux Security Moduleフレームワークには、20年以上にわたって維持されてきた中核的な保証が1つあります:
セキュリティモジュールは制限を追加することしかできない。制限を削除することは決してできない。
この保証は正しい。LIDはそれを破らない。
LIDはLSMフックを完全に迂回するカーネルコードパスを発見する — LSMフレームワークに相談せずにセキュリティ上重要な操作を実行するサブシステム。セキュリティチェック自体は正しい。問題は、カーネルがそもそも問い合わせないことにある。
各発見には、混同すべきではない2つの異なる側面があります:
アーキテクチャ上の盲点。「攻撃者はこれを悪用できるか?」という問いではなく:
セキュリティ上重要な操作が発生し、強制レイヤーがそれを評価すらしない場合、攻撃者が今日実際に悪用できるかどうかに関係なく、可視性ギャップが存在します。これはコンプライアンス、フォレンジック、多層防御の前提にとって重要です。
現実世界での悪用可能性に関する問い:
これら2つは別物です。 ある発見が重大な可視性ギャップ(あなたの監視が盲目である)であっても、実用的な権限昇格(攻撃者がすでにrootを必要とする)であるとは限りません。逆に、ある発見が最小限の前提条件で直接的な昇格経路になることもあります。
| Finding | Visibility Gap | Practical Escalation |
|---|---|---|
| LID-001 | 重大 — AppArmorは何も見ず、監査ログは空、フォレンジックの痕跡ゼロ | 限定的 — rootまたはCAP_BPF+CAP_PERFMONを必要とする(すでに特権あり)。権限昇格ではない。影響:ポリシー回避+監査の盲目化。 |
| LID-002 | 高 — security_file_receive()が発火せず、fd転送がすべてのLSMから不可視 | 高 — io_uring経由で非特権ユーザースペースから動作。いかなる特権もなしにLSM強制境界を越える。 |
| LID-003 | 高 — security_sb_mount()が迂回され、AppArmorのマウントポリシーはデッドコード | 中 — マウント名前空間へのアクセスを必要とする(ユーザー名前空間内のCAP_SYS_ADMIN)。多くのコンテナ設定で利用可能。 |
| LID-004 | 重大 — AppArmorは何も見ず、BPFフックはゼロ(0/9)、BPFトークン操作の監査トレースなし | 中 — ホストによるbpffs委任+ユーザー名前空間内のCAP_BPFを必要とする。BPF委任を備えたコンテナランタイム(LXD/Incus)で利用可能。 |
| LID-005 | 中 — コンテナインターフェース上のtc egress分類子がAF_XDPトラフィックを評価しない | 限定的 — コンテナeth0上のtc egressを迂回(検証済み)。Ciliumは迂回されない — ノード側veth ingressで強制+送信元IP検証(テスト済み)。影響はtc専用egressフィルタリングの素のDocker構成に限定。 |
各発見には特定のカーネル/設定/特権要件があります。環境が一致しない場合、その発見は再現しません。
| Condition | Required | Notes |
|---|---|---|
| カーネルバージョン | 5.x+ | 5.15、6.1、6.6、6.8でテスト済み |
CONFIG_BPF_SYSCALL | =y | 主要な全ディストロでデフォルト |
CONFIG_BPF_KPROBE_OVERRIDE | =y | Ubuntu/Debianは有効、RHELは無効 |
CONFIG_SECURITY_APPARMOR | =y | 対象LSMはAppArmorである必要あり |
| AppArmorプロファイル | Enforcing、対象パスへのdenyルール | 任意のパスベースdenyルールで動作 |
| 特権 | rootまたはCAP_BPF+CAP_PERFMON | 非特権では実行不可 |
kernel.lockdown | noneまたはintegrity | confidentialityモードはkprobeアタッチをブロック |
kernel.unprivileged_bpf_disabled | 無関係 | いずれにせよCAP_BPFが必要 |
fs.protected_hardlinks | クロスユーザーリンクでは0 | 1(デフォルト)でも同ユーザーのハードリンクは許可 |
| SELinuxをAppArmorの代わりに使用 | 動作しない | SELinuxはinodeベースであり、パス名ベースではない |
| Condition | Required | Notes |
|---|---|---|
| カーネルバージョン | 6.0+ | IORING_MSG_SEND_FDは6.0で追加 |
CONFIG_IO_URING | =y | 主要な全ディストロでデフォルト |
| 特権 | 不要 | 非特権ユーザースペースから動作 |
io_uring_disabled sysctl | 0(デフォルト) | 2は非特権をブロック、1はすべてをブロック |
| 対象LSM | 任意(SELinux、AppArmor、Smack) | security_file_receive()は汎用LSMフック |
kernel.lockdown | 無関係 | BPFは関与しない |
| Condition | Required | Notes |
|---|---|---|
| カーネルバージョン | 6.9+ | BPFトークンは6.9で導入 |
CONFIG_BPF_SYSCALL | =y | 主要な全ディストロでデフォルト |
CONFIG_SECURITY_APPARMOR | =y | Ubuntu/Debianのデフォルト |
| 委任付きbpffs | あり | ホストがdelegate_*オプションでマウントする必要あり |
| 特権 | ユーザー名前空間内のCAP_BPF | userns rootには簡単に利用可能 |
| SELinuxをAppArmorの代わりに使用 | 影響なし | SELinuxは9個すべてのBPFフックを実装 |
| Condition | Required | Notes |
|---|---|---|
| カーネルバージョン | 5.2+ | fsopen/fsmountは5.2で導入 |
CONFIG_SECURITY_APPARMOR | =y | 影響を受けるのはAppArmorのみ |
| 特権 | ユーザー名前空間内のCAP_SYS_ADMIN | unshare -mで利用可能 |
| SELinuxをAppArmorの代わりに使用 | 動作しない | SELinuxはsecurity_sb_kern_mount()を実装 |
| コンテナランタイム | seccompフィルタに依存 | Dockerデフォルトのseccompはfsopenをブロック — Podman/LXCはブロックしない場合あり |
| Condition | Required | Notes |
|---|---|---|
| カーネルバージョン | 4.18+ | AF_XDPは4.18で導入 |
CONFIG_XDP_SOCKETS | =y | 主要な全ディストロでデフォルト |
| 特権 | CAP_NET_RAWのみ | Docker、Kubernetesポッドでデフォルト |
| コンテナランタイム | Docker、K8s、LXC | デフォルトのケーパビリティセット |
| tcベースのネットワークポリシー | あり | Cilium eBPF、Calico、tc u32/flower |
| Environment | LID-001 | LID-002 | LID-003 | LID-004 | LID-005 |
|---|---|---|---|---|---|
| Ubuntu 22.04+(AppArmor、デフォルト) | 動作 | 動作 | 動作 | 動作(6.9+) | 動作 |
| Debian 12+(AppArmor) | 動作 | 動作 | 動作 | 動作(6.9+) | 動作 |
| RHEL/Fedora(SELinux) | 不可 | 動作 | 不可 | 不可 | 動作 |
lockdown=confidentiality | 不可 | 動作 | 動作 | 部分的 | 動作 |
| 非特権ユーザー | 不可 | 動作 | ユーザーns次第 | bpffs委任次第 | 不可 |
| コンテナ(CAP_BPFなし) | 不可 | io_uring次第 | seccomp次第 | 不可 | 動作 |
| コンテナ(CAP_NET_RAW削除) | 不可 | 次第 | 次第 | 不可 | 不可 |
| ID | Vector | Target | What Happens |
|---|---|---|---|
| LID-001 | eBPF kprobeパス名書き換え | AppArmor | kprobeがcopy_from_userの前にファイル名を書き換える → AppArmorは誤ったパスをチェック |
| LID-002 | io_uring MSG_RING SEND_FD | SELinux、AppArmor、Smack | fd転送がsecurity_file_receive()をスキップ — 他のすべてのfd転送はそれを呼ぶ |
| LID-003 | 新しいマウントAPI(fsopen/fsmount) | AppArmor | security_sb_mount()が呼ばれない — AppArmorの唯一のマウントフックが迂回される |
| LID-004 | BPFトークン委任 | AppArmor、Smack | BPFフックがゼロ — トークン作成、使用、ケーパビリティ委任が完全に不可視 |
| LID-005 | AF_XDP __dev_direct_xmit | tc egress、Cilium、Calico | デフォルトDockerからのコピーモードTXがtc分類子を迂回 — 偽造パケットがブリッジに到達 |
すべての発見は同じパターンに従います:``` ┌─────────────────────────────────────────────────────────────┐ │ THE LID PATTERN │ │ │ │ Kernel Subsystem A LSM Framework │ │ (eBPF / io_uring / mount API) (AppArmor / SELinux) │ │ │ │ ┌───────────────────┐ │ │ │ Performs operation │──── should call ──── security_*() │ │ │ or manipulates │ but │ │ │ security input │ DOESN'T ██ │ │ └───────────────────┘ │ │ │ │ The LSM framework is correct. │ │ The kernel just doesn't always use it. │ └─────────────────────────────────────────────────────────────┘
二つのカーネルサブシステム。相容れない信頼の前提。一つのギャップ。
<br>
---
## LID-001: eBPF パス名書き換え