CVE-2025-12958

Rankology SEO and Analytics Tool <= 2.0 - Incorrect Authorization to Authenticated (Editor+) Header & Footer Code Creation

lowImproper Authorization
2.7
CVSS Score
2.7
CVSS Score
low
Severity
2.5
Patched in
17d
Time to patch

Description

The Rankology SEO and Analytics Tool plugin for WordPress is vulnerable to unauthorized modification of data due to an incorrect capability check on the 'rankology_code_block' page in all versions up to, and including, 2.0. This makes it possible for authenticated attackers, with Editor-level access and above, to add header and footer code blocks.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.0
PublishedJanuary 6, 2026
Last updatedJanuary 23, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps required to analyze and exploit CVE-2025-12958, an improper authorization vulnerability in the Rankology SEO and Analytics Tool plugin. ### 1. Vulnerability Summary The **Rankology SEO and Analytics Tool** plugin (<= 2.0) contains a vulnerability that allows au…

Show full research plan

This research plan outlines the steps required to analyze and exploit CVE-2025-12958, an improper authorization vulnerability in the Rankology SEO and Analytics Tool plugin.

1. Vulnerability Summary

The Rankology SEO and Analytics Tool plugin (<= 2.0) contains a vulnerability that allows authenticated users with Editor privileges to inject arbitrary code (HTML/JavaScript) into the site's header and footer. This occurs because the plugin uses an insufficient capability check (likely edit_posts or similar Editor-level capability) when processing updates on the rankology_code_block administration page, instead of restricting this sensitive action to users with manage_options (Administrators).

By injecting malicious scripts into the header or footer, an Editor can achieve Stored Cross-Site Scripting (XSS) that executes in the context of all site visitors, including Administrators.

2. Attack Vector Analysis

  • Endpoint: Admin POST handler (likely wp-admin/admin.php?page=rankology_code_block or admin-post.php).
  • Action/Hook: The plugin likely uses an admin_init or admin_menu hook to handle POST data when the "Code Block" settings are saved.
  • Vulnerable Parameter: Parameters responsible for header and footer content (e.g., rankology_header_code and rankology_footer_code [inferred]).
  • Authentication: Authenticated, Editor role or higher.
  • Preconditions: The plugin must be active. The attacker must have a valid Editor session.

3. Code Flow

  1. Entry Point: An Editor user navigates to /wp-admin/admin.php?page=rankology_code_block.
  2. Form Submission: The user submits a form containing the desired header/footer scripts.
  3. Vulnerable Logic: The plugin intercepts the request (likely in a function hooked to admin_init or within the menu callback).
  4. Incorrect Capability Check: The code performs a check similar to:
    if ( current_user_can( 'edit_posts' ) ) { // VULNERABLE: Editors have this cap }
    instead of:
    if ( current_user_can( 'manage_options' ) ) { // Correct for sensitive settings }
  5. Persistence: The plugin saves the unsanitized or incorrectly authorized input into the WordPress options table (e.g., update_option('rankology_header_script', ...)).
  6. Sink: The saved code is echoed onto the frontend using hooks like wp_head or wp_footer.

4. Nonce Acquisition Strategy

To bypass CSRF protections, we must obtain a valid nonce generated for the rankology_code_block page.

  1. Identify Nonce: The nonce is likely created via wp_nonce_field() or wp_create_nonce() and localized/rendered in the admin page HTML.
  2. Access Page: Log in as an Editor and navigate to the vulnerable admin page.
  3. Extraction:
    • The execution agent will use browser_navigate to http://localhost:8080/wp-admin/admin.php?page=rankology_code_block.
    • Use browser_eval to extract the nonce from the form:
      browser_eval("document.querySelector('input[name=\"_wpnonce\"]')?.value || document.querySelector('input[name=\"rankology_nonce\"]')?.value")
    • Also, identify the exact names of the textareas for header/footer code.

5. Exploitation Strategy

The goal is to update the site header with a tracking script or a simple alert() to prove XSS.

Step-by-Step:

  1. Login: Authenticate as an Editor.
  2. Scrape Metadata: Visit the rankology_code_block page to get the _wpnonce and the exact parameter names used in the POST request.
  3. Construct Payload: Create a script payload: <script>console.log("CVE-2025-12958_Exploited")</script>.
  4. Execute POST Request: Use the http_request tool to send a multipart/form-data or URL-encoded POST request to the admin page.

Request Template (Inferred):

POST /wp-admin/admin.php?page=rankology_code_block HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Cookie: [Editor Cookies]

rankology_header_code=<script>alert(1)</script>&rankology_footer_code=&submit=Save+Changes&_wpnonce=[EXTRACTED_NONCE]

6. Test Data Setup

  1. Install Plugin: Ensure Rankology SEO and Analytics Tool version 2.0 is installed and active.
  2. Create Editor:
    wp user create editor_user editor@example.com --role=editor --user_pass=password123
  3. Permissions Check: Confirm the Editor can see the "Rankology" menu item (which itself is part of the vulnerability).

7. Expected Results

  • Response: A 302 Redirect back to the settings page with a settings-updated=true parameter or a 200 OK containing a success message.
  • Data Persistence: The malicious script is saved in the database.
  • Frontend Execution: When viewing the site homepage, the injected script <script>alert(1)</script> appears in the <head> or before </body>.

8. Verification Steps

  1. Check Database via CLI:
    wp option get rankology_header_code (Adjust option name based on findings).
  2. Verify Frontend Output:
    Use http_request to GET the site root and grep for the payload:
    http_request --url "http://localhost:8080/" | grep "alert(1)"
  3. Confirm Capability: Try to perform the same action as a Contributor (which should fail) to verify it is specifically an Editor+ authorization flaw.

9. Alternative Approaches

  • Direct Option Update (REST API): If the plugin registers these settings via register_setting without proper show_in_rest permissions/callbacks, check if they can be modified via POST /wp-json/wp/v2/settings.
  • Admin-Ajax/Admin-Post: If the settings page uses a dedicated handler, look for wp_ajax_rankology_save_code or admin_post_rankology_save_code hooks and verify if they lack current_user_can('manage_options').
Research Findings
Static analysis — not yet PoC-verified

Summary

The Rankology SEO and Analytics Tool plugin for WordPress is vulnerable to unauthorized data modification and Stored Cross-Site Scripting (XSS) in versions up to 2.0. Authenticated users with Editor-level privileges can inject arbitrary HTML and JavaScript into the site's header and footer because the plugin fails to restrict the 'Code Block' settings to Administrators.

Vulnerable Code

// File: includes/admin/class-rankology-admin.php (Inferred logic)

public function rankology_code_block() {
    // VULNERABLE: Editors typically have the 'edit_posts' capability which is used here instead of manage_options.
    if ( ! current_user_can( 'edit_posts' ) ) {
        wp_die( 'Unauthorized access' );
    }

    if ( isset( $_POST['rankology_save_code'] ) ) {
        check_admin_referer( 'rankology_code_nonce', 'rankology_nonce' );
        
        // Saves unsanitized code to site options without sufficient authorization
        update_option( 'rankology_header_code', $_POST['rankology_header_code'] );
        update_option( 'rankology_footer_code', $_POST['rankology_footer_code'] );
    }
}

Security Fix

--- a/includes/admin/class-rankology-admin.php
+++ b/includes/admin/class-rankology-admin.php
@@ -50,7 +50,7 @@
-    if ( ! current_user_can( 'edit_posts' ) ) {
+    if ( ! current_user_can( 'manage_options' ) ) {
         wp_die( 'Unauthorized access' );
     }

Exploit Outline

An attacker with Editor credentials logs into the WordPress admin panel and navigates to the 'rankology_code_block' menu page. By capturing the security nonce from the form and submitting a POST request containing arbitrary JavaScript in the 'rankology_header_code' or 'rankology_footer_code' parameters, the attacker bypasses intended access controls. The plugin saves these scripts to the options table, which are then rendered on the website's frontend via hooks like wp_head or wp_footer, allowing for persistent script execution.

Check if your site is affected.

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