CVE-2025-14342

SEO Plugin by Squirrly SEO <= 12.4.14 - Missing Authorization to Authenticated (Subscriber+) Cloud Service Disconnection

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
12.4.15
Patched in
1d
Time to patch

Description

The SEO Plugin by Squirrly SEO plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the sq_ajax_uninstall function in all versions up to, and including, 12.4.14. This makes it possible for authenticated attackers, with Subscriber-level access and above, to disconnect the site from Squirrly's cloud service.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=12.4.14
PublishedFebruary 18, 2026
Last updatedFebruary 19, 2026
Affected pluginsquirrly-seo

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-14342 (Squirrly SEO) ## 1. Vulnerability Summary The **SEO Plugin by Squirrly SEO** (versions <= 12.4.14) contains a missing authorization vulnerability in its AJAX handling logic. Specifically, the function `sq_ajax_uninstall` (inferred action: `sq_uninstall`…

Show full research plan

Exploitation Research Plan: CVE-2025-14342 (Squirrly SEO)

1. Vulnerability Summary

The SEO Plugin by Squirrly SEO (versions <= 12.4.14) contains a missing authorization vulnerability in its AJAX handling logic. Specifically, the function sq_ajax_uninstall (inferred action: sq_uninstall) fails to implement a capability check (e.g., current_user_can('manage_options')). This allows any authenticated user, including those with Subscriber roles, to trigger the plugin's disconnection from the Squirrly cloud service, potentially disrupting SEO features and deleting local configuration data associated with the cloud connection.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: sq_uninstall (inferred from function name sq_ajax_uninstall)
  • Method: POST
  • Authentication: Required (Subscriber-level or higher)
  • Parameters:
    • action: sq_uninstall
    • nonce: A WordPress nonce for the specific action (if enforced).
  • Preconditions: The plugin must be installed and active. The vulnerability is most impactful if the site is currently connected to the Squirrly Cloud (token stored in options).

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers an AJAX action for authenticated users.
    • Code: add_action('wp_ajax_sq_uninstall', array($controller, 'sq_ajax_uninstall'));
  2. Vulnerable Handler: The method sq_ajax_uninstall is executed.
  3. Missing Check: Inside sq_ajax_uninstall, the code likely proceeds to call a disconnection or cleanup method (e.g., SQ_Classes_RemoteController::uninstall()) without checking if the current user has administrative privileges.
  4. Sink: The plugin updates or deletes options like sq_cloud_token, sq_api_token, or site-specific metadata, effectively severing the link to the Squirrly cloud services.

4. Nonce Acquisition Strategy

Even though authorization is missing, WordPress AJAX handlers typically check for a CSRF nonce.

  1. Identify Localization: Squirrly SEO often localizes its configuration via wp_localize_script. We need to find the script handle and the variable name.
  2. Search for Nonce Action: Look for wp_create_nonce('sq_uninstall') or wp_create_nonce('sq_ajax_uninstall') in the plugin source.
  3. Extraction Steps:
    • Create a Subscriber user.
    • Log in as the Subscriber.
    • Access the WordPress Dashboard (/wp-admin/index.php).
    • Squirrly likely enqueues its admin scripts for all users if it doesn't restrict the admin_enqueue_scripts hook.
    • Use browser_eval to check for common Squirrly JS objects:
      • browser_eval("window.sq_config?.nonce")
      • browser_eval("window.SQ_Design?.nonce")
      • browser_eval("window.sq_uninstall_nonce") (inferred)
  4. Bypass Check: If the code uses check_ajax_referer('sq_uninstall', 'nonce', false) and fails to check the return value, the nonce can be omitted or be invalid.

5. Exploitation Strategy

Step 1: Authentication

Login as a Subscriber user to obtain a session cookie.

Step 2: Nonce Retrieval

Navigate to the dashboard and extract the nonce using the browser_eval tool.

Step 3: Trigger Disconnection

Send an authenticated POST request to the AJAX endpoint.

HTTP Request:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.local
Content-Type: application/x-www-form-urlencoded
Cookie: [Subscriber Cookies]

action=sq_uninstall&nonce=[EXTRACTED_NONCE]

Step 4: Verification

Confirm that the cloud connection is severed by checking plugin options.

6. Test Data Setup

  1. Install Plugin: Install Squirrly SEO version 12.4.14.
  2. Simulate Connection: Set a dummy cloud token in the database to verify it gets cleared.
    • wp option update sq_api_token "fake_token_12345"
    • wp option update sq_cloud_connect "1"
  3. Create Attacker:
    • wp user create attacker attacker@example.com --role=subscriber --user_pass=password123

7. Expected Results

  • The server should return a successful response (likely JSON {"success": true} or 1).
  • The database option sq_api_token or similar should be empty or deleted.
  • The Squirrly SEO dashboard should now show the site as "Disconnected" or prompt for login.

8. Verification Steps

After the HTTP request, use WP-CLI to check the state of the configuration:

  1. wp option get sq_api_token (Expected: Error or empty string).
  2. wp option get sq_cloud_connect (Expected: "0" or empty).

9. Alternative Approaches

  • Missing Nonce: If sq_uninstall does not exist, search for sq_disconnect or sq_ajax_disconnect.
  • Global Nonce: If no specific sq_uninstall nonce exists, check if Squirrly uses a generic nonce for all its AJAX actions, often found in sq_config.nonce.
  • Parameter Variation: Try adding confirmed=1 or force=1 if the function has internal logic checks to prevent accidental uninstalls.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.