Theori(Xint)の研究チームが、Linuxカーネルの暗号化サブシステムに潜むロジックバグ「Copy Fail(CVE-2026-31431)」を公表した。authencesnテンプレートとAF_ALGソケットの組み合わせで、非特権ユーザーが任意の読み取り可能ファイルのページキャッシュに4バイトの制御可能書き込みを発生させられる。研究者によれば、わずか732バイトのPythonスクリプトで/usr/bin/suを改変してroot権限を奪取できる。Ubuntu 24.04・Amazon Linux 2023・RHEL 10.1・SUSE 16が検証済みで、2017年以降のすべてのLinuxカーネルが該当する。コンテナエスケープにも直結するため、ECS・EKSを運用するチームは即時に対応方針を決める必要がある。
この記事ではLinuxカーネルのページキャッシュ書き込み脆弱性CVE-2026-31431の影響と対策を解説します。サプライチェーンや依存関係を含む全体的な防御戦略はサプライチェーンセキュリティ2026|攻撃手法・防御ツール・実践チェックリストをご覧ください。
この記事のポイント
- 非特権ユーザーが
AF_ALGソケットとsplice()を組み合わせ、/usr/bin/suなどsetuid実行ファイルのページキャッシュを4バイト書き換えてroot奪取できる。 - オンディスクのファイルは無傷のため、Tripwireや
rpm -Vなどのファイル整合性チェックでは検出不可。「メモリ上だけが汚染されたsetuidバイナリ」が走る。 - ページキャッシュはホスト全体で共有されるため、ECS・EKSノードに同居する別コンテナや別Podへ影響が伝播する。マルチテナントクラスタでは特に危険。
Copy Fail(CVE-2026-31431)とは:4バイト書き込みでroot奪取まで届く脆弱性
Copy Failは、Linuxカーネルの暗号化APIであるAF_ALGソケットと、AEADテンプレートauthencesnの動作が結合したロジック系の権限昇格脆弱性だ。CWEとしては「Improper Restriction of Operations within the Bounds of a Memory Buffer」(CWE-119)に近い。Theori Xintが2026年4月に公開したアドバイザリで割り当てられたCVE番号はCVE-2026-31431。
「Copy Fail」というニックネームは、copy_from_user系の入出力がインプレース最適化(同じバッファを入力と出力に使う)によって書き込み禁止であるべきページにまで到達してしまうことを指している。
| 項目 | 内容 |
|---|---|
| CVE | CVE-2026-31431(2026年4月22日割り当て) |
| 公表 | 2026年4月、Theori Xint Labs |
| 種別 | ロジックバグ/インプレース最適化の境界違反 |
| 必要な権限 | 非特権ユーザー(AF_ALGソケットが使えれば十分) |
| 書き込みサイズ | 4バイト(seqno_loの値、AADで制御可能) |
| エクスプロイトサイズ | 約732バイトのPythonスクリプト |
| 検出難度 | オンディスク不変のためFIMで検出不可 |
| 対象カーネル | 2017年以降のすべてのLinuxカーネル |
なぜ非特権ユーザーで成立するのか
AF_ALGは本来、ハードウェア暗号アクセラレータをユーザー空間アプリケーションへ公開するためのカーネル暗号APIだ。socket(AF_ALG, SOCK_SEQPACKET, 0)で誰でもオープンでき、CAP_SYS_ADMINなどの特権は要らない。デフォルトのDocker・containerd・runc seccompプロファイルはsocket()システムコール自体を許可しているため、コンテナ内の非特権プロセスからも到達できる。
splice()は、ファイルディスクリプタからソケットへコピーなしでデータを渡すシステムコールだ。コピーが省かれるということは、カーネル内では「ページキャッシュ上の物理ページへのポインタ」がそのまま暗号化サブシステムに渡るということを意味する。
攻撃の仕組み:authencesn・AF_ALG・splice()の3つの罠
Copy Failは単一バグではなく、Linuxカーネルへ独立に入った3つの変更の合流点で生まれた脆弱性だ。歴史的経緯を押さえると、なぜ2017年以降のすべてのカーネルで成立するのかが見える。
| 年 | 変更 | 役割 |
|---|---|---|
| 2011 | authencesnテンプレート追加 |
IPsec ESN用に「宛先バッファを一時領域として使う」初期設計 |
| 2015 | AF_ALGにAEAD対応+splice()パス追加 |
ユーザー空間からページキャッシュ参照を渡せるように |
| 2017 | algif_aead.cがインプレース動作に変更 |
req->src == req->dstでページキャッシュが「書き込み可能」扱いに |
authencesnが4バイトを書き戻す仕組み
authencesnは、IPsecのExtended Sequence Number(ESN)を扱うための復号テンプレートで、復号中にAAD(追加認証データ)の一部であるseqno_lo(4バイト)を宛先スキャッタリスト末尾の特定オフセットへ書き戻す。通常の用途では復号成功時の出力タグ領域に当たるはずだった。
しかし2017年のインプレース最適化のもとでは、dst[assoclen + cryptlen]の位置がチェーン化されたページキャッシュページに落ちる。HMAC検証が失敗してもこの書き込みは取り消されないため、攻撃者は「タグ検証を意図的に失敗させながらページを書き換える」操作が可能になる。
エクスプロイトの骨格(PoCコード抜粋)
公開されたPoCの中核は以下のような構造だ。splice()で渡された同一ページが暗号化サブシステムの出力バッファにもなるため、カーネルが4バイトを書き込む先は攻撃者が制御できる。
import socket, struct, os, fcntl
# AF_ALG ソケットで authencesn(hmac(sha256),cbc(aes)) にバインド
sock = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
sock.bind((
b"aead",
b"authencesn(hmac(sha256),cbc(aes))",
0, # feat
16, # aeadtype (IVlen=16)
))
# 鍵をセット(32+32+16 バイト: SHA256 HMAC鍵 + AES鍵 + ESN)
key = bytes(80)
sock.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, key)
op = sock.accept()[0]
# su のページキャッシュを splice() で渡す
fd = os.open("/usr/bin/su", os.O_RDONLY)
# pipe 経由で splice を繋ぐ
rfd, wfd = os.pipe()
os.splice(fd, 0, wfd, 0, 4096)
# AAD バイト4-7に書き込みたい4バイト値をセット
want_bytes = struct.pack("<I", 0xdeadbeef)
aad = b"\x00" * 4 + want_bytes + b"\x00" * 8
# sendmsg + recvmsg でトリガー
# ... (HMAC 失敗するが書き込みは完了)
オフセット制御はspliceのオフセット・長さ・assoclenの組み合わせで決まる。4バイト書き込みを繰り返すことで、実行ファイルの任意のシェルコードを注入する。
ページキャッシュ汚染がディスクに書き戻されない理由
カーネルはsplice()経由で渡されたページを「ダーティ」としてマークしない。authencesnの書き込みは暗号処理内部の副作用として発生するため、ページフレームのdirtyフラグが立たない。その結果:
sync/fsyncを呼んでもディスクに書き戻されない- Tripwire・IMA(Integrity Measurement Architecture)・
rpm -V・dpkg -Vはオンディスクのハッシュを検証するため、ページキャッシュ上の改ざんを見逃す - マシン再起動でページキャッシュは消える(揮発性攻撃)が、再起動するまで改ざんが持続する
検出不可の盲点 FIM(ファイル整合性監視)ツールはこの脆弱性を検出できない。「ファイルのハッシュが一致している」は「実行されるコードが正常」を意味しなくなっている。ランタイム保護(eBPFベースのシステムコール監視等)でのみ検知が見込める。
ECS・EKSへの影響:ページキャッシュはコンテナ境界を越える
この脆弱性がコンテナ運用で特に深刻なのは、ページキャッシュがホスト全体で共有されているからだ。Linuxのページキャッシュは名前空間(namespace)やcgroupでは分離されない。コンテナ1台が同じページをsplice()で取得した瞬間から、そのページへの書き込みはホスト全体、ひいては同一ホスト上のすべてのコンテナに波及する。
(ページキャッシュ共有)"] --> B["ECS Task A
(通常アプリ)"] A --> C["ECS Task B
(悪意あるコンテナ)"] A --> D["ECS Task C
(別チームのサービス)"] C -- "CVE-2026-31431
ページキャッシュ書き込み" --> A A -- "汚染された su/bash
がホスト全体に影響" --> B A --> D style C fill:#ff6b6b,color:#fff style A fill:#ffa94d,color:#fff
運用形態別の影響と対応優先度
| 運用形態 | カーネル管理 | 影響 | 対応方法 | 優先度 |
|---|---|---|---|---|
| ECS on Fargate | AWS管理 | AWSがホストを管理。パッチ適用はAWS側 | タスク再起動で新ホストへ移行。AWS告知を待機 | 中 |
| ECS on EC2(AL2023) | 自己管理 | Amazon Linux 2023 (kernel 6.18.8)が検証済み被影響 | AL2023 AMI更新+インスタンス入れ替え | 高 |
| EKS Managed Node | AWS管理(AMI) | EKS最適化AMIのカーネル更新待ち | AMI更新+ノードローテーション | 高 |
| EKS Self-managed Node | 自己管理 | 同上。自分でAMI管理 | dnf update kernel後ノード再起動 |
高 |
| Fargate for EKS | AWS管理 | Fargateと同様にAWS側で対応 | Pod再デプロイで新ホストへ | 中 |
| EC2上の自前Docker | 自己管理 | ホストカーネルが直接影響 | dnf/apt update kernel後に再起動 |
高 |
マルチテナントEKSで最も危険なシナリオ
EKSのノードに複数チームのPodが同居する構成(共有ノード)では、あるNamespaceの悪意あるPodが脆弱性を突き、ホスト上のすべてのPodに影響するページを汚染できる。これは実質的なコンテナエスケープであり、ノード全体の制圧に繋がる。
Theoriのアドバイザリでは「Part 2:Kubernetes コンテナエスケープ」が予告されており、より詳細な攻撃手順が近く公開される予定だ。CI/CDランナー(外部からコードを受け取って実行する環境)は最優先でパッチを適用すべきだ。同様のRCEがCI/CDパイプラインで問題になった事例はGitHub RCE脆弱性CVE-2026-3854解説:git push一発でサーバー乗っ取り、Wizが発見も参照されたい。
seccompプロファイルとの関係
デフォルトのDockerおよびKubernetesのseccompプロファイル(runtime/default)は、socket(AF_ALG, ...)を許可している。AF_ALGを明示的にブロックするカスタムseccompプロファイルを適用するか、後述のカーネルモジュール無効化を行わない限り、コンテナ内からも攻撃可能だ。
対策と即時ミティゲーション:パッチ適用前にやれること
根本対策はカーネルパッチ(コミットa664bf3d603d)の適用だ。algif_aead.cがアウトプレース動作に戻され、req->srcとreq->dstが分離される。ページキャッシュが書き込み可能スキャッタリストに入らなくなる。
パッチの確認方法
# カーネルバージョンとパッチ状況確認
uname -r
# Amazon Linux 2023 の場合
dnf check-update kernel
# Ubuntu の場合
apt-get update && apt-cache policy linux-image-$(uname -r)
# カーネルモジュール algif_aead のロード状況確認
lsmod | grep algif
即時ミティゲーション(パッチ適用前)
パッチが適用されるまでの間、algif_aeadカーネルモジュールをブロックすることで攻撃経路を閉じられる。AF_ALGソケット自体は生きているが、authencesnがバインドできなくなる。
# algif_aead モジュールをブロック(ホスト側で実行)
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
# 既にロード済みの場合はアンロード
sudo rmmod algif_aead 2>/dev/null || echo "already unloaded or builtin"
# 設定を永続化
sudo dracut -f # RHEL/AL2023 系
# または
sudo update-initramfs -u # Debian/Ubuntu 系
ECS on EC2 での対応手順
- Launch Template または AMI のユーザーデータに上記
modprobe.d設定を追加 - 新しい AMI または起動設定でインスタンスを入れ替え(In-place再起動でも可)
- AL2023 カーネルアップデート後は設定を元に戻してよい
カスタムseccompプロファイルで AF_ALG をブロック
モジュール無効化ができない環境(Fargateや共有ノード)では、コンテナレベルでAF_ALGソケット作成をブロックするseccompプロファイルを使う。
{
"defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [
{
"names": ["socket"],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 36,
"op": "SCMP_CMP_NE"
}
]
}
]
}
上記はAF_ALGのドメイン値36に対するsocket()呼び出しを拒否する例だ。KubernetesではPodのannotationまたはsecurityContext.seccompProfileで適用できる。
Amazon Linux 2023(ECS/EKS の主要OS)での緊急対応フロー
# Step 1: 現在のカーネルバージョン確認
uname -r
# 例: 6.1.xx-xxx.xxx.amzn2023.x86_64
# Step 2: 最新カーネルへアップデート(パッチ適用版を確認)
sudo dnf update -y kernel kernel-modules
# Step 3: 再起動(ECSタスクを停止してEC2を再起動)
sudo reboot
# Step 4: 再起動後にバージョン確認
uname -r
# Step 5: algif_aead モジュールの状態確認(ミティゲーション適用中の場合)
lsmod | grep algif_aead
eBPFによるランタイム検知:FIMが効かないなら何で検知するか
ファイル整合性監視が効かないため、ランタイムでのシステムコール監視が唯一の検知手段になる。AF_ALGソケットを生成するsocket(AF_ALG, SOCK_SEQPACKET, 0)呼び出しは、通常のWebアプリやAPIサービスではほぼ発生しない。この呼び出しをトリガーにアラートを発報する。
Falcoルール例
- rule: AF_ALG Socket Created
desc: Detect AF_ALG socket creation which may indicate CVE-2026-31431 exploitation
condition: >
syscall.type = socket and
socket.domain = AF_ALG
output: >
AF_ALG socket created (user=%user.name pid=%proc.pid
container=%container.id image=%container.image.repository)
priority: WARNING
tags: [cve-2026-31431, kernel, privilege-escalation]
eBPFプローブによる直接監視
// AF_ALG = 38 (architectureによって異なる)
SEC("kprobe/sys_socket")
int detect_af_alg(struct pt_regs *ctx) {
int domain = (int)PT_REGS_PARM1(ctx);
if (domain == AF_ALG) {
bpf_printk("AF_ALG socket created by pid %d\n", bpf_get_current_pid_tgid());
// アラート送信またはプロセスシグナル
}
return 0;
}
FalcoやTetragonなどeBPFベースのランタイムセキュリティツールを導入していれば、既存のルールセットを拡張するだけで対応できる。AI支援のセキュリティツールが脆弱性を発見する事例についてはYoloFS:AIエージェントのファイルシステム安全性とサンドボックス設計で別の観点から解説している。
まとめ:FIM検出不可のステルス脆弱性に備える
Copy Fail(CVE-2026-31431)は「2017年以降のすべてのLinuxカーネルが影響」「FIMで検出不可」「コンテナ境界を越える」という3点が重なる、対応コストが高い脆弱性だ。
| 脆弱性特性 | Copy Fail の挙動 |
|---|---|
| 必要権限 | 非特権ユーザー(CAP不要) |
| 書き込みサイズ | 4バイト(繰り返し可) |
| オンディスク影響 | なし(ページキャッシュのみ) |
| FIMでの検出 | 不可 |
| コンテナエスケープ | ページキャッシュ共有により可能 |
| 対象カーネル | 2017年以降すべて |
| ミティゲーション | algif_aeadブロックまたはseccomp強化 |
対応の優先度は次の順だ。
- マルチテナントEKS・CIランナー — 即時
algif_aeadブロック+カーネルパッチ待機 - ECS on EC2(Amazon Linux 2023) — AMI更新スケジュール確定+ミティゲーション適用
- ECS on Fargate — AWS側のパッチ告知を監視し、タスク再起動計画を立てる
- EKS Managed Node — Amazon EKS最適化AMIの更新リリースを確認
「オンディスクが正常だから安全」という前提は、このクラスの脆弱性では通用しない。FIMに頼らないランタイム監視層(eBPF/Falco/Tetragon)を防御スタックに加えることが、今後のカーネル脆弱性への備えとしても有効だ。
サプライチェーン攻撃全体の文脈でのコンテナ・カーネルセキュリティはサプライチェーンセキュリティ2026|攻撃手法・防御ツール・実践チェックリストにまとめている。
FAQ
Q. ECS Fargateは自分でパッチを当てる必要がありますか?
FargateのホストOSはAWSが管理しているため、自分でカーネルパッチを当てる必要はない。ただし、AWSがパッチを適用したホストに実際に移行するためにはタスクの再起動(新しいタスクの起動→古いタスクの停止)が必要になることがある。AWSからのセキュリティアドバイザリを確認し、指示があればタスクを再デプロイすること。
Q. Dockerコンテナ内のプロセスが AF_ALG ソケットを使えるのはなぜですか?
DockerのデフォルトのseccompプロファイルはLinuxのシステムコールの大部分を許可しており、socket()もその一つだ。AF_ALG(ドメイン値36または38、アーキテクチャによる)に対するフィルタは含まれていない。docker run --security-opt seccomp=/path/to/custom.jsonで明示的にブロックするか、ホスト側でalgif_aeadモジュールをアンロードする必要がある。
Q. Amazon Linux 2023 は具体的にどのカーネルバージョンが修正済みですか?
本記事執筆時点(2026年4月30日)では、ALASリリースノートにKernel修正の正確なバージョン番号が掲載されていない。AWSのALAS-2026-*系アドバイザリを定期購読し、dnf update kernelを実行してバージョンを確認すること。パッチコミット番号はa664bf3d603d(algif_aead: アウトプレース動作へ戻す)で、このコミットが含まれるバージョンかどうかで判定できる。
Q. 再起動なしにページキャッシュの汚染を除去できますか?
現時点では再起動が最も確実だ。特定ファイルのページキャッシュをドロップするにはecho 3 > /proc/sys/vm/drop_cachesが使えるが、これはシステム全体のページキャッシュを消去するため本番環境では副作用が大きい。また、攻撃が継続する環境では再汚染を防げない。根本対策はカーネルパッチの適用だ。
Q. Kubernetes PodSecurityAdmission(PSA)では防げますか?
PSAのrestrictedプロファイルはPod仕様レベルの制限(非特権コンテナ、rootfs read-only等)を強制するが、AF_ALGソケット作成自体を禁止する機能はない。seccompプロファイルをRuntimeDefault以上に設定するだけでは不十分で、AF_ALGをブロックするカスタムseccompプロファイルが必要だ。
参照ソース
- Copy Fail: Unauthorized Page Cache Write on Linux Distributions (CVE-2026-31431) - Xint.io
- Linux Kernel Git: algif_aead.c - コミット a664bf3d603d
- Linux Kernel Documentation: AF_ALG - Crypto API User Space Interface
- Falco Security - Kernel Module and eBPF Based Runtime Security
- Amazon Linux Security Center - ALAS Advisories