
CVE-2026-31431 用の C ベースのローカル権限昇格エクスプロイト。AF_ALG 暗号インターフェースにおける Linux カーネルの脆弱性を悪用し、ページキャッシュ操作を介して root アクセスを提供します。
Copy Fail (CVE-2026-31431) は、Linuxカーネルにおける論理的な脆弱性であり、ローカルの非特権ユーザーがスーパーユーザー(root)権限へ昇格することを可能にします。この脆弱性は Local Privilege Escalation (LPE) のクラスに属し、レースコンディションやメモリアドレスの推測といった複雑な悪用条件を必要とせず、2017年以降にリリースされたほとんどのLinuxディストリビューションで「そのまま」動作します。
このリポジトリには、オリジナルのPythonエクスプロイトをC言語に移植したものが、詳細なコメント付きで含まれており、静的コンパイルと最小限の環境での使用に適しています。
この脆弱性は、Linuxカーネルの暗号化サブシステムにおける論理エラーに起因し、AF_ALG(カーネル暗号APIのインターフェース)とページキャッシュ(page cache)メカニズムの処理に関連しています。
このエラーは2017年、AEAD(Authenticated Encryption with Associated Data)ブロック暗号化操作をその場で(in-place)実行することで余分なバッファリングを排除する最適化が追加された際に導入されました。authencesn(AEAD暗号テンプレートの一部)アルゴリズムにおけるバッファ境界の不適切な処理により、割り当てられたバッファの範囲外に4バイトが書き込まれ、ページキャッシュの管理構造が破損します。
その結果、カーネルは読み取り専用で開かれたファイル(O_RDONLY)であっても、データをページキャッシュに書き戻すことが可能になります。
AF_ALGソケットを開き、AEADアルゴリズムauthencesn(hmac(sha256),cbc(aes))を初期化します。setsockopt()を通じて異常なパラメータが設定されます:
sendmsg()とコントロールメッセージを通じて復号操作が開始されます。splice()システムコールが、対象ファイル(O_RDONLYで開かれた)から暗号ソケットへデータを移動します。authencesnのエラーによりファイルのページキャッシュが破損し、「復号された」データがキャッシュに書き戻されます。root権限でのコード実行につながります。影響を受けるディストリビューション(algif_aeadモジュールがロードされたカーネルを使用している場合):
特に重要な点: コンテナ環境(Docker、LXC、Kubernetes)では、ホストカーネルにalgif_aeadモジュールがロードされている場合、コンテナ内のプロセスはデフォルトでAF_ALGサブシステムにアクセスできます。これにより、コンテナの分離が破られ、ホストマシンの制御を取得するリスクが生じます。
脆弱性の確認:
# algif_aeadモジュールがロードされているか確認
lsmod | grep algif
# カーネルにAF_ALGが存在するか確認
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)
オリジナルのエクスプロイトはPython(約732バイト)で書かれていました。このC言語への移植には以下の特徴があります:
libzのみが必要です。straceで検証済み)。recv() — Pythonのtry/exceptの動作を再現し、ハングアップを防ぎます。移植中に判明したPython版との主な違い:
# libzが必要(zlib1g-dev または zlib-devel)
gcc -o copyfail copyfail.c -lz -static -Wall -O2
./copyfail
悪用に成功すると、パスワードを要求せずにrootアクセスを提供するパッチ適用済みの/usr/bin/suが実行されます。
期待される出力:
================================================================
CVE-2026-31431 'Copy Fail' Exploit
================================================================
[+] /usr/bin/su が開かれました
[+] 40チャンク
[*] 40/40 OK
# id
uid=0(root) gid=0(root) groups=0(root)
以下は、対応するシステムコールを含むエクスプロイトの各ステップの詳細な解説です:
socket(AF_ALG, SOCK_SEQPACKET, 0);
bind(sock, {sa_family=AF_ALG, salg_type="aead",
salg_name="authencesn(hmac(sha256),cbc(aes))"}, 88);
カーネル暗号APIへのアクセス用ソケットが作成されます。authencesn(Authenticated Encryption with Sequence Numbers)アルゴリズムは、AES-CBCを暗号化に、HMAC-SHA256を認証に使用する複合AEADアルゴリズムです。
setsockopt(sock, SOL_ALG, ALG_SET_KEY, key, 40);
setsockopt(sock, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 4);
accept(sock, NULL, NULL); // conn_sock
sendmsg(conn_sock, {payload="AAAA"+data,
cmsg=[(SOL_ALG, 3, 4ゼロ), // ALG_SET_OP = DECRYPT
(SOL_ALG, 2, 0x10+19ゼロ), // ALG_SET_IV
(SOL_ALG, 4, 0x08+3ゼロ)]}, // ALG_SET_AEAD_ASSOCLEN
MSG_MORE);
操作のための接続が作成されます。sendmsg()とコントロールメッセージ(CMSG)を通じてパラメータが設定されます:
ALG_OP_DECRYPT = 0)。これらの異常により、カーネルのメモリ管理に不整合が生じます。
pipe2(pipe_fds, O_CLOEXEC);
splice(target_fd, &src_off, pipe_fds[1], NULL, o, 0);
splice(pipe_fds[0], NULL, conn_sock, NULL, o, 0);
splice()は、userspaceを経由せずにファイルディスクリプタ間でデータを移動するシステムコールです。データはpipeメカニズムを通じてカーネルレベルで移動されます。
splice(target_fd -> pipe): 対象ファイル(/usr/bin/su)のデータがpipeに入ります。splice(pipe -> conn_sock): pipeのデータが「暗号文」として暗号ソケットに入ります。重要なポイント: Python(およびこの移植版)では、pipeのオフセットはNULLとして渡され、カーネルが自動的に位置を管理できるようにします。
fcntl(conn_sock, F_SETFL, O_NONBLOCK);
recv(conn_sock, buf, 8 + t, 0);
recv()呼び出しにより、カーネルは暗号操作を完了します。通常モードでは復号データが返されますが、異常なパラメータにより、PythonではEBADMSG、C(O_NONBLOCK付き)ではEAGAINエラーが返されます。エラーは無視されます — ページキャッシュの破損はsplice()の段階ですでに発生しています。
ページキャッシュ(page cache)は、ファイルの内容をRAMにキャッシュするものです。プロセスがO_RDONLYでファイルを開くと、カーネルはこのキャッシュからの読み取りのみを許可します。しかし、この脆弱性によりこの制限を回避できます:
write()呼び出し時にVFSレベルで行われますが、splice()はこれらのチェックを迂回してページキャッシュレベルで直接動作します。変更はディスクではなくRAM内でのみ発生します。これにより、標準的な整合性チェックツールでは攻撃を検出することが困難になります。再起動またはページキャッシュのクリア後、攻撃の痕跡は消えます。
Linuxカーネルを修正を含むバージョンに更新する。
algif_aeadモジュールを無効化する:
# モジュールのロードを禁止
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/algif_aead.conf
# モジュールをアンロード(ロードされている場合)
sudo rmmod algif_aead
追加の推奨事項:
AF_ALGへのアクセスを禁止する。/usr/bin/suファイルは変更されますか?いいえ。変更はページキャッシュ(RAM)内でのみ発生します。ディスク上のファイルの内容は変更されません。システム再起動後、ページキャッシュはクリアされ、ファイルは元の状態に戻ります。
検出は以下を通じて可能です:
auditd、strace)。AF_ALGソケット使用の異常の分析。標準的な整合性チェックツール(AIDE、Tripwire)は、ディスク上のファイルが変更されないため、変更を検出できません。
このコードは教育および研究目的のみで提供されています。著者は、このコードの違法な使用について一切の責任を負いません。システム所有者の明示的な許可なしにエクスプロイトを使用することは違法であり、刑事責任を問われる可能性があります。
自分が所有するシステム、またはセキュリティテストの明示的な書面による許可を得ているシステムでのみ使用してください。
| コンポーネント | 説明 |
|---|
| Linuxカーネル | 2017年以降、修正パッチが適用されるまでのすべてのバージョン |
| サブシステム | crypto(モジュール algif_aead) |
| インターフェース | AF_ALG — カーネル暗号APIへのユーザーアクセス |
| システムコール | AF_ALGソケットと組み合わせたsplice() |
| パラメータ | Python | C(この移植版) |
|---|
sendmsg()フラグ | MSG_MORE | MSG_MORE |
splice()フラグ | 0 | 0 |
| pipe内のオフセット | NULL | NULL |
| キーサイズ | 40バイト | 40バイト |
cmsg_len | 20/36/20 | 20/36/20(ハードコード) |
| pipeの作成 | pipe2(fds, O_CLOEXEC) | pipe2(fds, O_CLOEXEC) |
recv() | try/except付きブロッキング | 非ブロッキング(O_NONBLOCK) |