Receive Notifications After Form Submitting – Form Notify for Any Forms <= 1.1.10 - Unauthenticated Authentication Bypass via LINE OAuth Callback
Description
The Form Notify plugin for WordPress is vulnerable to Authentication Bypass in versions up to and including 1.1.10. This is due to the plugin trusting user-controlled cookie data to determine which WordPress account to authenticate after a LINE OAuth login. When LINE doesn't provide an email address (which is common), the plugin falls back to reading the 'form_notify_line_email' cookie value without verifying that the LINE account is associated with that email address. This makes it possible for unauthenticated attackers to gain access to any user account on the site, including administrator accounts, by completing a LINE OAuth flow with their own LINE account while injecting a malicious cookie containing the target victim's email address.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
What Changed in the Fix
Changes introduced in v1.1.11
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-5229 (Form Notify Authentication Bypass) ## 1. Vulnerability Summary The **Receive Notifications After Form Submitting – Form Notify for Any Forms** plugin (version <= 1.1.10) is vulnerable to an unauthenticated authentication bypass. The vulnerability resides…
Show full research plan
Exploitation Research Plan: CVE-2026-5229 (Form Notify Authentication Bypass)
1. Vulnerability Summary
The Receive Notifications After Form Submitting – Form Notify for Any Forms plugin (version <= 1.1.10) is vulnerable to an unauthenticated authentication bypass. The vulnerability resides in the LINE OAuth callback logic. Specifically, when a user authenticates via LINE but does not provide an email address (e.g., they denied the email scope), the plugin trusts user-controlled data (the form_notify_line_email cookie) to determine which WordPress account to log into.
An attacker can use their own LINE account to satisfy the OAuth signature verification and then provide a target administrator's email in the cookie to gain full administrative access.
2. Attack Vector Analysis
- Endpoint:
/wp-json/form-notify/v1/callback(REST API) - Method:
GET - Preconditions:
- The plugin must have LINE Login configured (
form_notify_line_login_channel_idandsecretset). - An attacker must have a valid LINE account.
- The attacker must know the email address of a target administrator.
- The plugin must have LINE Login configured (
- Vulnerable Parameters:
form_notify_line_email(Cookie). - Authentication: Unauthenticated. The
permission_callbackfor the REST route is__return_true.
3. Code Flow
- Entry Point: The attacker initiates the flow by calling
GET /wp-json/form-notify/v1/login. - State Generation:
Route::get_api_login()(insrc/APIs/Line/Login/Route.php) generates astateusingmd5(time()), stores it in a transientform_notify_line_state_{state}, and redirects the user to LINE. - OAuth Verification: After the attacker authenticates with their LINE account, LINE redirects back to
/wp-json/form-notify/v1/callback?code={CODE}&state={STATE}. - Callback Handling:
Route::get_api_callback()(insrc/APIs/Line/Login/Route.php):- Validates that the provided
statematches the transient/session. - Calls
SDK::get_access_token($code)to exchange the code for a token from LINE. - Calls
SDK::get_line_profile(...)which callshttps://api.line.me/oauth2/v2.1/verifyto validate the ID Token.
- Validates that the provided
- Vulnerable Sink:
- If LINE does not provide an email (
$user->emailis empty), the code (in the vulnerable version as described) falls back to reading$_COOKIE['form_notify_line_email'](Inferred based on description; provided snippet inRoute.phpline 126 shows a hardcoded fallback$user_raw_id . '@line.com', suggesting the cookie usage was the original implementation or exists in a specific configuration path). - The determined
$user_emailis passed toUser::is_member($user_email, ...)and thenUser::login(...)insrc/APIs/Line/Login/User.php.
- If LINE does not provide an email (
- Authentication Bypass:
User::login()callswp_set_auth_cookie($this->user->ID)for the user found via the malicious email, effectively logging the attacker in as the victim.
4. Nonce Acquisition Strategy
The vulnerable REST routes (form-notify/v1/login and form-notify/v1/callback) do not require a WordPress nonce.
The register_api_route function in src/APIs/Line/Login/Route.php defines the permission_callback as true for both endpoints. These are public OAuth endpoints meant for external redirects.
If a nonce were needed for any reason, the plugin localizes lineLoginButtonParams in form-notify.php:
- JS Variable:
window.lineLoginButtonParams - Extraction:
browser_eval("window.lineLoginButtonParams.some_key")(though no nonce is registered in the providedwp_localize_scriptcall).
5. Exploitation Strategy
Step 1: Initialize Session and State
Call the login endpoint to populate the transient on the server.
- Request:
GET /wp-json/form-notify/v1/login - Tool:
http_request - Objective: Follow the redirect to capture the
stateparameter generated by the plugin.
Step 2: Prepare Mock LINE Responses (Local Test Environment)
Because the PoC environment cannot connect to real LINE APIs, the agent must intercept the wp_remote_request calls made by SDK.php to api.line.me.
- Mock Token Response: Return a valid-looking
access_tokenandid_token. - Mock Verify Response: Return a JSON object where
subis the attacker's LINE ID, butemailis omitted.
Step 3: Execute Callback with Malicious Cookie
Send the callback request with the valid state and the target administrator's email in the cookie.
- URL:
/wp-json/form-notify/v1/callback?code=mock_code&state={STATE_FROM_STEP_1} - Method:
GET - Cookie Header:
form_notify_line_email=admin@example.com - Tool:
http_request
Step 4: Capture Auth Cookies
The response to Step 3 should include Set-Cookie headers for wordpress_logged_in_....
6. Test Data Setup
- Target User: Ensure an administrator exists with email
admin@example.com.wp user create attacker attacker@example.com --role=administrator(or use existing).
- Plugin Configuration: The plugin needs a dummy Channel ID to enable the routes.
wp option update form_notify_line_login_channel_id "123456"wp option update form_notify_line_login_channel_secret "secret"
7. Expected Results
- The request to
/wp-json/form-notify/v1/callbackshould result in a302 Redirect(likely to the admin dashboard or the URL stored inlogin_redirect_url). - The response headers should contain a valid WordPress authentication cookie (
wordpress_logged_in_...) for the administrator account.
8. Verification Steps
- Identify the session: Capture the
wordpress_logged_incookie from the exploit response. - Verify Identity: Use the captured cookie to make a request to
/wp-json/wp/v2/users/me.- Expected: The response JSON should show
slug: "admin"andcapabilities: { administrator: true }.
- Expected: The response JSON should show
- Database Check: Verify the
form_notify_line_user_idmeta was added to the admin user.wp user meta get 1 form_notify_line_user_id
9. Alternative Approaches
If the form_notify_line_email cookie is not the direct injection point:
- Check
lgmodeParameter: TheUser::set_login_redirect_urlfunction insrc/APIs/Line/Login/User.phpprocesses thelgmodeparameter and sets alogin_redirect_urlcookie. Check if this can be used for Open Redirect to steal tokens if the site is configured with other SSO. - Sign-Up Flow: If the target email does not exist, the plugin calls
User::sign_up(). An attacker could potentially register a new account with arbitrary roles ifform_notify_line_btn_user_roleis misconfigured.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.