CVE-2026-31431 に対する軽量で可逆的な seccomp ベースの緩和策です。これは、Linux カーネルの algif_aead / authencesn 暗号サブシステムにおけるローカル権限昇格の脆弱性です。
種別: ローカル権限昇格 (LPE)
影響を受けるコンポーネント: Linux カーネル crypto/algif_aead.c - インプレース AEAD 操作
攻撃プリミティブ: authencesn AEAD アルゴリズムのスクラッチ書き込みパスを介して、読み取り可能な任意のファイルのページキャッシュへの 4 バイトの制御可能な書き込み。/etc/passwd を標的にすることで、攻撃者は自分の UID を 0 (root) に変更し、su を介して root シェルを取得できます。
影響を受けるカーネル: カーネル 6.12+、6.17+、6.18+ で確認済み。RHEL/CentOS 4.18/5.14 カーネルでも再現されています。
検証済み環境: Rocky Linux 8 (カーネル 4.18) および Rocky Linux 9 (カーネル 5.14) - エクスプロイトは完全にブロックされ、安全な削除が確認されています。
根本原因: コミット 72548b093ee3 によりインプレース AEAD 操作が導入されました。スプライスされたページキャッシュページが宛先 scatterlist として使用される場合、AEAD 復号中に AAD seqno_lo フィールドが誤ってページキャッシュに書き戻されます。
上流の修正: アウトオブプレース AEAD 操作へのリバート。
このソリューションには2 つのコンポーネントがあります:
PAM モジュール (pam_block_afalg.so) - 主要な防御策。PAM がセッションオープン時 (pam_sm_open_session) にロードし、ユーザーコードが実行される前に socket(AF_ALG, ...) をブロックする seccomp BPF フィルタを適用します。これにより、su -c、su -、SSH、TTY ログインなど、PAM 認証済みのすべてのセッションがカバーされます。
スタンドアロンバイナリ (block_afalg) - オプション。PAM 以外のシナリオ (cron ジョブ、systemd サービス、手動呼び出しなど) で特定のプログラムをラップできます。
seccomp フィルタ:
socket(AF_ALG, ...) のみをブロックします (EACCES を返す)setuid、su、sudo を含む) には影響なしPAM セッションオープン (su、ssh、login など)
|
v
pam_block_afalg.so (pam_sm_open_session)
|
+-- チェック: カーネルは脆弱か? (socket(AF_ALG) を試行)
| |
| +-- いいえ --> PAM_SUCCESS を返す (no-op)
| |
| +-- はい --> prctl(PR_SET_SECCOMP, BPF フィルタ)
| |
| +-- sshd 子プロセスで seccomp フィルタが有効
| +-- ユーザーのシェルとすべての子プロセスに継承
| +-- socket(AF_ALG, ...) は EACCES を返す
v
ユーザーのシェル / コマンドが seccomp 保護付きで実行
|
+-- su、sudo、および他のすべてのシステムコールは正常に動作
+-- AF_ALG ソケットのみがブロックされる
| ファイル | 目的 |
|---|---|
pam_block_afalg.c | PAM モジュールのソース。セッションオープン時に seccomp フィルタを適用します。 |
pam_minimal.h |
gcc (コンパイル用)libpam (ランタイム、通常はプリインストール済み)# 1. PAM モジュールをコンパイル
gcc -Wall -O2 -fPIC -shared -o pam_block_afalg.so pam_block_afalg.c \
/usr/lib64/libpam.so.0
# 2. インストール (su、sshd、login に PAM 設定を自動追加)
sudo ./deploy.sh install
# 3. 検証 (新しいセッションである必要があります)
cat /proc/self/status | grep Seccomp
# 表示されるはず: Seccomp: 2
python3 -c "
import socket
try:
s = socket.socket(38,2,0); s.close()
print('VULNERABLE')
except OSError:
print('BLOCKED')
"
# 表示されるはず: BLOCKED
# 4. アンインストール
sudo ./deploy.sh remove
| コマンド | 説明 |
|---|---|
deploy.sh install | PAM モジュールをコンパイルし、/lib64/security/ にインストール、PAM 設定を自動追加 |
deploy.sh remove | 完全アンインストール: モジュールの削除、PAM 設定のクリーンアップ、ファイルの削除 |
deploy.sh status | インストール状態、PAM 設定、カーネル状態を表示 |
PAM 以外のシナリオでは、block_afalg を直接使用します:
# コンパイル
gcc -Wall -O2 -o block_afalg block_afalg.c
# AF_ALG をブロックしてコマンドを実行
./block_afalg python3 your_script.py
./block_afalg bash
python3 -c "
import socket
try:
s = socket.socket(38, socket.SOCK_SEQPACKET, 0)
s.close()
print('VULNERABLE: AF_ALG socket available')
except:
print('SAFE: AF_ALG socket blocked or unavailable')
"
# seccomp ステータスを確認
cat /proc/self/status | grep Seccomp
# Seccomp: 0 = 保護されていない
# Seccomp: 2 = 保護されている
# AF_ALG ソケットをテスト
python3 -c "
import socket
try:
s = socket.socket(38,2,0)
s.close()
print('AF_ALG available - NOT protected')
except OSError:
print('AF_ALG blocked - PROTECTED')
"
# PAM ログを確認
grep pam_block_afalg /var/log/secure
# 表示されるはず: seccomp filter applied, AF_ALG blocked
x86_64 の __NR_socket) をハードコードしています。他のアーキテクチャではシステムコール番号を更新する必要があります。exec() 呼び出しはカバーされません (その場合は block_afalg を使用してください)。remove でクリーンアップすることもできます。yum update kernel を実行してからモジュールを削除します。このツールは、許可されたセキュリティテストおよび防御目的でのみ提供されます。所有しているシステム、または明示的に評価を許可されたシステムでのみ使用してください。
| 最小限の PAM 型定義 (pam-devel なしでコンパイル可能)。 |
block_afalg.c | スタンドアロンの seccomp ラッパーバイナリ。PAM 以外での使用向け。 |
deploy.sh | デプロイスクリプト。PAM モジュールのコンパイル、インストール、管理を行います。 |