
LinuxカーネルLPE CVE-2026-31431向けの調査・検出ツールキット。エクスプロイト解析、YARAルール、auditd/Falco検出、パッチ適用ガイド、ラボ環境を含む。
algif_aead のローカル権限昇格CISA KEV | CVSS 7.8 HIGH | Linuxカーネル 4.14〜2026年初頭に影響(約9年間)
CVE-2026-31431 は、通称 「Copy Fail」 と呼ばれる、Linuxカーネルの暗号サブシステムにおける高深刻度のローカル権限昇格(LPE)脆弱性です。低権限のローカルユーザーは、パッチ未適用のシステム上で数秒でroot権限に昇格できます。
| 属性 | 値 |
|---|---|
| CVE | CVE-2026-31431 |
| 通称 | Copy Fail |
| CVSS v3.1 | 7.8 HIGH |
| 攻撃ベクトル | ローカル |
| 必要な権限 | 低 |
| ユーザー操作 | なし |
| コンポーネント | crypto/algif_aead.c — authencesn テンプレート |
| 導入時期 | 2017年(コミット 72548b093ee3) |
| 公開時期 | 2026年 |
| 潜伏期間 | 約9年間 |
| CISA KEV | あり |
| 公開PoC | あり(732バイトのスタンドアロンPythonスクリプト) |
detection/check_vulnerable.sh を実行します。CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
| メトリクス | 値 | 根拠 |
|--------|-------|-----------|
| 攻撃ベクトル | **ローカル** | シェルアクセス(SSH、コンテナexec、物理)が必要 |
| 攻撃の複雑さ | **低** | 信頼性が高く、完全自動化 — レースコンディションは不要 |
| 必要な権限 | **低** | 任意の非特権ユーザーアカウント |
| ユーザー操作 | **なし** | 被害者の操作は不要 |
| 機密性への影響 | **高** | システム全体の完全侵害 |
| 完全性への影響 | **高** | システム全体の完全侵害 |
| 可用性への影響 | **高** | システム全体の完全侵害 |
### 脅威の状況
| 要素 | 評価 |
|--------|-----------|
| PoCの入手可能性 | 公開済み、実戦投入可能、732バイトのスタンドアロンPython |
| エクスプロイトの信頼性 | 高 — テスト済みのディストリビューション間で修正なしに動作 |
| 検出の難易度 | 高 — ディスク書き込みなし、ダーティページなし |
| 攻撃者に必要なスキル | 低 — 公開PoCを持つスクリプトキディ |
| CISA KEV | 2026年に追加 — 積極的に監視中 |
| Microsoft Defender | 積極的な調査中としてフラグ付け |
### 影響を受ける環境
| 環境 | リスク |
|-------------|------|
| ベアメタルLinuxサーバー | 重大 |
| Linux VM(クラウドまたはオンプレミス) | 重大 |
| Kubernetesノード | 重大(コンテナエスケープも可能) |
| Dockerホスト | 重大 |
| 共有ホスティング / マルチテナント | 重大 |
| WSL2 / Windows上のLinux | カーネルバージョンごとに評価 |
---
## 3. 技術的な詳細解説
### 3.1 背景: AF_ALGとAEAD
Linuxカーネルは、**AF_ALGソケット**(`AF_ALG = 38`)を介して暗号操作をユーザースペースに公開しています。このインターフェース(`algif_aead`)により、非特権アプリケーションはカーネルモードのコードを必要とせずに、カーネルの暗号ハードウェアアクセラレータを呼び出すことができます。
**AEAD**(認証付き暗号化と関連データ)アルゴリズム(AES-GCMやChaCha20-Poly1305など)は、TLS、ディスク暗号化、VPNプロトコルで広く使用されています。脆弱なテンプレートは`authencesn` — 拡張シーケンス番号(ESN)サポートを備えた`hmac(sha256)` + `cbc(aes)`を使用するAEAD構成で、IPsecで一般的に使用されています。
### 3.2 根本原因
2017年、コミット`72548b093ee3`がパフォーマンス最適化として`algif_aead`に**インプレースAEAD操作**を導入しました — これにより、暗号エンジンが同じバッファを読み書きできるようになりました。これは欠陥がありました:```
The bug chain:
1. Caller binds AF_ALG socket to:
authencesn(hmac(sha256),cbc(aes))
2. Caller sends a decryption request via sendmsg() with specific flags
3. Caller uses splice() to feed PAGE CACHE PAGES from an open file
descriptor directly into the socket's scatterlist
4. The authencesn template, during ESN header processing, uses the
OUTPUT BUFFER as scratch space — writing 4 bytes past the
expected output boundary
5. Because the scatterlist contains page cache pages (not private
copies), this scratch write lands DIRECTLY IN THE PAGE CACHE
6. Page cache is shared kernel-wide — all processes reading the
same file now see the modified bytes
Key insight: splice() is zero-copy — it hands page cache references
to the socket. The in-place "optimization" then writes INTO those
pages. No dirty bit is set because the write goes through the crypto
engine, not the normal write path.
この脆弱性により、攻撃者が読み取り用に開くことができる任意のファイルのページキャッシュへの、制御された4バイト書き込みが可能になります:
この書き込みは繰り返し可能です — エクスプロイトは4バイト書き込みをループさせて、より大きなコードシーケンスにパッチを適用します。
[1] Open /usr/bin/su (or any setuid-root binary) for reading ↓ [2] Map a copy to find target instruction bytes (e.g., UID check, execve path, security gate) ↓ [3] Compute exact page cache offset of target bytes ↓ [4] Set up AF_ALG socket → authencesn(hmac(sha256),cbc(aes)) ↓ [5] splice() the target binary's page cache into the socket ↓ [6] Trigger decryption → authencesn scratch write patches the target bytes in page cache (4 bytes per iteration) ↓ [7] Repeat for each 4-byte patch needed ↓ [8] Execute /usr/bin/su → runs root-owned setuid binary but now with attacker-controlled code in page cache ↓ [9] Root shell
### 3.5 標準的な防御が失敗する理由
| 防御策 | 回避されるか? | 理由 |
|---------|-----------|--------|
| ファイル整合性監視(Tripwire/AIDE) | **はい** | ディスク上の変更なし |
| IDSファイルハッシュチェック | **はい** | ディスクのバイトは不変 |
| `inotify` ファイル監視 | **はい** | VFS書き込みイベントなし |
| SELinux / AppArmor | **部分的** | プロセスは制御するが、暗号エンジンを介したページキャッシュ書き込みは制御しない |
| 読み取り専用マウント | **はい** | ページキャッシュはマウント経由ではなくメモリ内で変更される |
| バイナリに対する `auditd` の `watch` | **はい** | 監査はVFS書き込みを監視する — これはVFSを迂回する |
### 3.6 影響を受けるカーネルバージョン
| ブランチ | 影響を受ける範囲 | 修正版 |
|--------|-------------------|------------|
| 4.14.x | すべて(脆弱性の起源) | アップストリーム修正なし(EOL) |
| 5.4.x(LTS) | すべて | ディストリビューションのバックポートが必要 |
| 5.10.x(LTS) | すべて | ディストリビューションのバックポートが必要 |
| 5.15.x(LTS) | すべて | ディストリビューションのバックポートが必要 |
| 6.1.x(LTS) | ≤ 6.1.129 | **6.1.130+** |
| 6.6.x(LTS) | ≤ 6.6.86 | **6.6.87+** |
| 6.12.x(LTS) | ≤ 6.12.22 | **6.12.23+** |
| 6.15-rc | rcで修正済み | **6.15-rc+** |
> ディストリビューションのカーネルは、異なるバージョン番号で修正をバックポートしている場合があります。必ずお使いのディストリビューションのセキュリティ勧告を確認してください。
---
## 4. 攻撃手法 — レッドチーム
> **認可が必要です。** このセクションは、防御側が攻撃者の視点を理解するためのものです。所有しているシステム、または明示的な書面によるテスト許可を得たシステムでのみ実行してください。
### 4.1 前提条件
- ターゲット上での低権限シェル(SSH、コンテナexec、RCEチェーン)
- Python 3.10+ **または** コンパイル済みCバイナリ
- `algif_aead` が利用可能な未パッチのカーネル
### 4.2 偵察```bash
# Check if vulnerable
uname -r
cat /proc/crypto | grep -A10 "authencesn"
lsmod | grep algif_aead
# Verify setuid target exists
ls -la /usr/bin/su /usr/bin/sudo /usr/bin/passwd
元の研究者(Theori)は、完全に動作する732バイトのスタンドアロンPython PoCを公開しました:
python3 copy_fail_exp.py
python3 copy_fail_exp.py /usr/bin/passwd
A local copy is available at `exploit/poc.py`. See `exploit/README.md` for technical breakdown.
### 4.4 Container Escape Scenario
Because the Linux page cache is shared between all processes on the same host (including host and containers):```
Attacker in container → patches /usr/bin/su in HOST page cache
Host user runs su → executes attacker code as root on host
This works even from non-privileged containers, as long as the host kernel is vulnerable.
これは本リポジトリの主な焦点です。
任意の Linux システムで検知スクリプトを実行します:```bash chmod +x detection/check_vulnerable.sh sudo ./detection/check_vulnerable.sh
**チェック内容:**
- カーネルバージョンを既知の脆弱性のある範囲と照合
- `algif_aead` モジュールのロード状態とブラックリスト状態
- `/proc/crypto` 内の `authencesn` の有無
- setuid バイナリのページキャッシュ整合性(root 権限が必要)
- ディストリビューション固有のパッチ適用状況
- アクティブな悪用の兆候を示す実行中プロセス
タイムスタンプ付きのレポートが `/tmp/cve-2026-31431-report-*.txt` に保存されます。
### 5.2 YARA 検出
`detection/yara/` に2つの YARA ルールが用意されています:
| ルールファイル | 目的 |
|-----------|---------|
| `cve_2026_31431_base.yar` | 既知の公開 PoC と完全に一致 |
| `cve_2026_31431_enhanced.yar` | 難読化、コンパイル済み、および亜種のエクスプロイトを検出 |```bash
# Install YARA
apt-get install yara # Debian/Ubuntu
dnf install yara # RHEL/Fedora
apk add yara # Alpine
# Scan running process executables
sudo yara -r detection/yara/cve_2026_31431_enhanced.yar /proc/*/exe 2>/dev/null
# Scan common dropper locations
sudo yara -r detection/yara/cve_2026_31431_enhanced.yar /home /tmp /var/tmp /dev/shm
# Scan uploaded files / quarantine
yara detection/yara/cve_2026_31431_base.yar <suspect_file>
拡張ルールが重要な理由: 攻撃者は公開されているPython PoCを難読化する可能性があります(文字列をbase64エンコードする、アルゴリズム名をXORエンコードする、Cバイナリにコンパイルする、シンボルを削除する)。拡張ルールは、エクスプロイトを壊さずに削除できない不変条件を標的にすることで、これらの亜種を検出します:
authesnを受け取る必要があるsplice()を使用する必要がある38)を作成する必要がある/etc/audit/rules.d/cve-2026-31431.rulesに配置します:```bash
-a always,exit -F arch=b64 -S socket -F a0=38 -k cve_2026_31431_afalg
-a always,exit -F arch=b64 -S splice -k cve_2026_31431_splice
-a always,exit -F arch=b64 -S init_module -S finit_module -k cve_2026_31431_modload
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -k cve_2026_31431_suid_exec
リロード:```bash
augenrules --load && service auditd restart
クエリによる悪用試行の検索:```bash
ausearch -k cve_2026_31431_afalg --start today
ausearch -k cve_2026_31431_afalg -k cve_2026_31431_splice --start today
### 5.4 Falco / eBPF 検出
`/etc/falco/rules.d/cve-2026-31431.yaml` に追加します:```yaml
- rule: CVE-2026-31431 AF_ALG Socket Creation
desc: Detects unprivileged process creating AF_ALG socket (family 38) — required step for Copy Fail exploit
condition: >
syscall.type = socket and
evt.arg.domain = 38 and
not user.uid = 0 and
not proc.name in (known_crypto_daemons)
output: >
CVE-2026-31431 exploitation attempt - AF_ALG socket (user=%user.name
uid=%user.uid pid=%proc.pid cmd=%proc.cmdline)
priority: CRITICAL
tags: [cve-2026-31431, lpe, kernel, crypto]
- list: known_crypto_daemons
items: [strongswan, charon, pluto, openssl]
- rule: CVE-2026-31431 Splice After AF_ALG
desc: Detects splice() syscall shortly after AF_ALG socket creation — exploitation sequence
condition: >
syscall.type = splice and
not user.uid = 0 and
evt.elapsed < 5000000000
output: >
CVE-2026-31431 splice after AF_ALG socket (user=%user.name pid=%proc.pid)
priority: CRITICAL
tags: [cve-2026-31431, lpe]
このエクスプロイトはディスクへの書き込みを行わずにページキャッシュを改変するため、標準的なFIMツールでは検知できません。このチェックはアクティブな悪用を検出します:```bash #!/bin/bash
SETUID_BINS=("/usr/bin/su" "/usr/bin/sudo" "/usr/bin/passwd")
for binary in "${SETUID_BINS[@]}"; do [[ -f "$binary" ]] || continue LIVE_HASH=$(sha256sum "$binary" | awk '{print $1}') echo 3 | sudo tee /proc/sys/vm/drop_caches > /dev/null # flush page cache DISK_HASH=$(sha256sum "$binary" | awk '{print $1}') if [[ "$LIVE_HASH" != "$DISK_HASH" ]]; then echo "CRITICAL: Page cache tampering detected on $binary" echo " Pre-flush: $LIVE_HASH" echo " Post-flush: $DISK_HASH" else echo "OK: $binary page cache matches disk" fi done
> **本番環境に関する注意:** `drop_caches` はパフォーマンスに影響を与えます。メンテナンスウィンドウ中、または重要でないシステムで先に実行してください。
### 5.6 侵害指標 (IoCs)
| IoC タイプ | 指標 | 信頼度 |
|----------|-----------|-----------|
| 文字列 (バイナリ/スクリプト) | `authencesn(hmac(sha256),cbc(aes))` | 高 |
| 16進バイト | `78 DA AB 77 F5 71 63 62 64 64` (zlib ペイロードヘッダー) | 高 |
| システムコールシーケンス | `socket(38,5,0)` → `bind()` → `splice()` | 高 |
| ネットワーク | なし — 完全にローカル | N/A |
| ファイル | ディスク書き込みなし (ステルス) | — |
| プロセス | AF_ALG ソケットを持つ短命な Python/C プロセス | 中 |
| ページキャッシュ | setuid バイナリのページキャッシュ ≠ ディスク上のハッシュ | 重大 |
### 5.7 SIEM 検出クエリ
**Splunk (auditd ソース):**```spl
index=linux_audit sourcetype=auditd action=SYSCALL syscall=socket a0="0x26"
| join pid [
search index=linux_audit sourcetype=auditd action=SYSCALL syscall=splice
]
| where (_time - join_time) < 30
| table _time host user pid cmd a0
| eval severity="CRITICAL"
Elastic KQL:```kql event.action: "SYSCALL" AND process.args: "socket" AND auditd.data.a0: "0x26" AND NOT user.id: "0"
**Microsoft Sentinel (KQL):**```kql
Syslog
| where Facility == "kern" or ProcessName == "audit"
| where SyslogMessage contains "socket" and SyslogMessage contains "a0=0x26"
| extend UserName = extract("uid=([0-9]+)", 1, SyslogMessage)
| where UserName != "0"
| project TimeGenerated, Computer, UserName, SyslogMessage
| order by TimeGenerated desc
自動パッチスクリプトを実行します:```bash chmod +x patch/patch.sh sudo ./patch/patch.sh
### 6.1 即時緩和策(再起動不要*)```bash
# Blacklist the module permanently
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
echo "install authencesn /bin/false" | sudo tee -a /etc/modprobe.d/disable-algif-aead.conf
# Unload if currently loaded
sudo rmmod algif_aead 2>/dev/null || echo "Not loaded — mitigation active after config"
# Verify
lsmod | grep algif_aead && echo "WARNING: still loaded — reboot needed" || echo "OK: not loaded"
*algif_aead がすでにロードされている場合、ブラックリストを完全に有効にするには再起動が必要です。
副作用: AF_ALG 経由でカーネルの AEAD インターフェースを使用するアプリケーション(一般的ではありません。ほとんどは OpenSSL ユーザースペースを使用します)は失敗する可能性があります。標準の TLS、ディスク暗号化、VPN ツールは通常影響を受けません。
kubectl get nodes -o wide
kubectl drain --ignore-daemonsets --delete-emptydir-data
kubectl uncordon
ノードの自動アップグレーダー(Karpenter、マネージドノードグループ)または利用可能な場合はクラスターノードプールのローテーションを使用します。
### 6.4 パッチ適用後の検証```bash
# Re-run detection script
sudo ./detection/check_vulnerable.sh
# Quick manual verification
uname -r # confirm new kernel version
lsmod | grep algif_aead # should be empty
cat /proc/crypto | grep authencesn # should return nothing (or still listed but module blacklisted)
検出ツールを安全にテストするための最小限のAlpine Dockerラボが用意されています。```bash cd lab/ docker compose up -d docker exec -it cve-2026-31431-lab /bin/sh
/cve-2026-31431/detection/check_vulnerable.sh
> **重要:** Docker コンテナはホストカーネルを共有します。このラボは**ホストカーネルの**脆弱性状態をテストします。脆弱性の結果は実際のホストシステムを反映します — これは現実的な評価のための意図的な設計です。
特定の脆弱なカーネルバージョンで隔離テストを行うには、固定されたカーネルを持つ専用VMを使用してください。VMセットアップのガイダンスは `lab/README.md` を参照してください。
---
## 8. 参考情報
| リソース | リンク |
|----------|------|
| NVDアドバイザリ | https://nvd.nist.gov/vuln/detail/CVE-2026-31431 |
| 元の研究 | https://copy.fail |
| 技術解説 | https://xint.io/blog/copy-fail-linux-distributions |
| 公開PoC | https://github.com/theori-io/copy-fail-CVE-2026-31431 |
| CISA KEVカタログ | https://www.cisa.gov/known-exploited-vulnerabilities-catalog |
| カーネル修正 — リバートコミット | `a664bf3d603d` / `fafe0fa2995a` |
| 脆弱なコミット | `72548b093ee3` |
| Microsoft Defenderアドバイザリ | Microsoft Defender脅威インテリジェンスブログ |
---
## リポジトリ構造```
cve-2026-31431/
├── README.md ← This document
├── exploit/
│ ├── README.md ← Technical exploit breakdown
│ └── poc.py ← Public PoC (theori-io, for reference)
├── detection/
│ ├── README.md ← Detection guide
│ ├── check_vulnerable.sh ← Vulnerability & IoC detection script
│ └── yara/
│ ├── cve_2026_31431_base.yar ← Detects known public PoC
│ └── cve_2026_31431_enhanced.yar ← Detects obfuscated/compiled variants
├── patch/
│ ├── README.md ← Remediation guide
│ └── patch.sh ← Automated patch/mitigation script
└── lab/
├── README.md ← Lab setup guide
├── Dockerfile ← Alpine-based lab container
└── docker-compose.yml ← Lab orchestration
この研究は、教育および防御的なセキュリティ目的のみで提供されています。すべてのツールは、防御者が保護を許可されたシステム上でCVE-2026-31431を検出し、修復するのを支援するために設計されています。
リポジトリはrippsecによって管理されています
| プロパティ | 値 |
|---|
| 書き込みサイズ | 4バイト |
| オフセット制御 | あり — spliceオフセット経由で攻撃者が制御可能 |
| ターゲット | 読み取り可能な任意のファイルのページキャッシュ |
| ダーティページのマーキング | なし |
| ディスク上の変更 | なし |
| タイムスタンプの更新 | なし |
| カーネルログへの記録 | なし(auditdが設定されている場合を除く) |
| Technique | ID | Notes |
|---|
| Exploitation for Privilege Escalation | T1068 | 中核となる手法 |
| Abuse Elevation Control Mechanism: Setuid/Setgid | T1548.001 | Setuid バイナリのハイジャック |
| Hijack Execution Flow | T1574 | インメモリでのバイナリパッチ |
| Indicator Removal: Timestomp | T1070.006 | タイムスタンプは更新されない |
| Indirect Command Execution | T1202 | パッチ適用済みバイナリがシェルを実行 |
| ディストリビューション | 更新コマンド |
|---|
| Ubuntu / Debian | apt-get update && apt-get upgrade linux-image-generic && reboot |
| RHEL / CentOS / Rocky | dnf update kernel && reboot |
| Amazon Linux 2 | yum update kernel && reboot |
| Amazon Linux 2023 | dnf update kernel && reboot |
| SUSE / SLES | zypper update kernel-default && reboot |
| Arch Linux | pacman -Syu linux && reboot |
| Alpine Linux | apk update && apk upgrade linux-lts && reboot |
| Debian | apt-get update && apt-get upgrade linux-image-amd64 && reboot |