CVE-2026-6391

Sentence To SEO (keywords, description and tags) <= 1.0 - Cross-Site Request Forgery to Stored Cross-Site Scripting via Settings Page Parameters

mediumCross-Site Request Forgery (CSRF)
6.1
CVSS Score
6.1
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Sentence To SEO (keywords, description and tags) plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 1.0. This is due to missing or incorrect nonce validation on the create_admin_page() function. This makes it possible for unauthenticated attackers to inject malicious web scripts and update plugin settings via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.0
PublishedMay 19, 2026
Last updatedMay 20, 2026
Affected pluginsentence-to-seo
Research Plan
Unverified

This exploitation research plan outlines the technical steps required to demonstrate the Cross-Site Request Forgery (CSRF) to Stored Cross-Site Scripting (XSS) vulnerability in the **Sentence To SEO** plugin (<= 1.0). --- # Exploitation Research Plan: CVE-2026-6391 ## 1. Vulnerability Summary The…

Show full research plan

This exploitation research plan outlines the technical steps required to demonstrate the Cross-Site Request Forgery (CSRF) to Stored Cross-Site Scripting (XSS) vulnerability in the Sentence To SEO plugin (<= 1.0).


Exploitation Research Plan: CVE-2026-6391

1. Vulnerability Summary

The Sentence To SEO plugin fails to implement proper Cross-Site Request Forgery (CSRF) protections (nonces) in its administrative settings management logic. Specifically, the create_admin_page() function handles the processing and saving of plugin settings without verifying a security nonce. This allows an attacker to forge a request on behalf of an authenticated administrator. Because the settings parameters (such as keywords and descriptions) are subsequently stored and rendered in the WordPress admin dashboard without sufficient output sanitization or escaping, the CSRF leads to Stored Cross-Site Scripting (XSS).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin.php?page=sentence-to-seo (Inferred slug based on plugin name).
  • Vulnerable Action: The POST request processed by the create_admin_page() function (or the logic it calls to handle $_POST data).
  • Authentication Level: Requires a victim with administrator privileges to be logged in and interact with a malicious link or page.
  • Payload Parameters:
    • sentence_to_seo_keywords (Inferred)
    • sentence_to_seo_description (Inferred)
    • sentence_to_seo_tags (Inferred)

3. Code Flow (Inferred)

  1. Registration: The plugin registers an admin page via add_menu_page() or add_options_page() in the admin_menu hook, pointing to create_admin_page() as the callback.
  2. Processing: Inside create_admin_page(), the code checks if a form has been submitted: if ( isset( $_POST['submit'] ) ).
  3. Missing Check: The function lacks a call to check_admin_referer() or wp_verify_nonce().
  4. Storage: User-provided input from $_POST is passed directly to update_option().
  5. Sink: When the settings page is reloaded, the stored options are retrieved via get_option() and echoed into the HTML input fields or the page body without esc_attr() or esc_html().

4. Nonce Acquisition Strategy

Based on the vulnerability description ("missing or incorrect nonce validation"), there are two possibilities:

Case A: Nonce check is entirely missing

If check_admin_referer is absent, no nonce is required. This is the most likely scenario for this vulnerability type.

Case B: Nonce is present but validation is flawed

If the plugin uses a nonce but exposes it on the page:

  1. Use browser_navigate to go to /wp-admin/admin.php?page=sentence-to-seo.
  2. Use browser_eval to extract the nonce from the hidden form field:
    browser_eval("document.querySelector('input[name=\"_wpnonce\"]')?.value")

Note: Since the goal is CSRF, the attacker cannot typically read this nonce from a different origin. However, if the plugin enqueues a script on the frontend that includes the nonce via wp_localize_script, it could be retrieved there.

5. Exploitation Strategy

The goal is to update the plugin settings with a malicious script payload using a forged POST request.

Step 1: Identify Parameters

First, the researcher must identify the exact keys used in the update_option calls.

  • Action: Inspect the HTML form on the settings page or use wp-cli to list options: wp option list --search="sentence_to_seo*".

Step 2: Construct the CSRF Exploit

A malicious HTML page will be served to the administrator.

Payload Request (Internal to PoC Agent):

POST /wp-admin/admin.php?page=sentence-to-seo HTTP/1.1
Host: [TARGET_HOST]
Content-Type: application/x-www-form-urlencoded
Cookie: [ADMIN_COOKIES]

sentence_to_seo_keywords=%3Cscript%3Ealert%28document.domain%29%3C%2Fscript%3E&submit=Save+Changes

Step 3: Trigger Execution

  1. The agent uses http_request to simulate the POST request (representing the result of the CSRF).
  2. The agent then navigates to the plugin settings page to trigger the Stored XSS.

6. Test Data Setup

  1. Plugin Installation: Ensure sentence-to-seo version 1.0 is active.
  2. User Setup: Create a standard administrator user.
  3. Default State: Confirm the settings are currently empty or set to benign values.

7. Expected Results

  • The POST request should return a 302 Redirect back to the settings page or a 200 OK indicating success, despite the absence of a nonce.
  • Upon navigating to the settings page, the browser should execute the JavaScript in the payload (e.g., triggering an alert or a console.log).

8. Verification Steps

After performing the HTTP request, verify the injection using wp-cli:

# Check if the option in the database contains the payload
wp option get sentence_to_seo_keywords

Expected output: <script>alert(document.domain)</script>

9. Alternative Approaches

If the settings are not output on the admin page, they might be output on the frontend in the <head> section as meta tags.

  1. Frontend Check: Use http_request to GET the site's homepage.
  2. Verification: Search the response body for:
    <meta name="keywords" content="<script>alert(document.domain)</script>">
  3. Bypass Attempt: If check_admin_referer exists, check if it only validates the nonce if the parameter is present (Bypass 3 in the Knowledge Base). Attempt the request by omitting the nonce parameter entirely.

Check if your site is affected.

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