CVE-2026-8707

NS Product icon badge <= 1.2.4 - Reflected Cross-Site Scripting via PHP_SELF

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.1
CVSS Score
6.1
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The NS Product icon badge plugin for WordPress is vulnerable to Reflected Cross-Site Scripting via PHP_SELF in all versions up to, and including, 1.2.4 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick a user 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.2.4
PublishedMay 26, 2026
Last updatedMay 27, 2026
Affected pluginproduct-icon-badge
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-8707 ## 1. Vulnerability Summary The **NS Product icon badge** plugin for WordPress (<= 1.2.4) is vulnerable to **Reflected Cross-Site Scripting (XSS)**. The vulnerability arises from the improper neutralization of the `PHP_SELF` server variable. In certain ve…

Show full research plan

Exploitation Research Plan: CVE-2026-8707

1. Vulnerability Summary

The NS Product icon badge plugin for WordPress (<= 1.2.4) is vulnerable to Reflected Cross-Site Scripting (XSS). The vulnerability arises from the improper neutralization of the PHP_SELF server variable. In certain versions of PHP and server configurations, $_SERVER['PHP_SELF'] includes the path information provided in the URL. If a plugin echoes this variable directly into an HTML attribute (most commonly a <form action="...">) without using esc_url(), an attacker can append a malicious script payload to the URL path. This payload is then reflected in the page source and executed by the victim's browser.

2. Attack Vector Analysis

  • Endpoint: Any WordPress admin page or frontend page where the plugin renders a form or link using PHP_SELF. Based on the plugin type, this is most likely found in the admin settings page.
  • Vulnerable Variable: $_SERVER['PHP_SELF'].
  • Attack Parameter: The URL path (specifically, characters following the script name).
  • Authentication Requirement:
    • Attacker: Unauthenticated (PR:N).
    • Victim: An Administrator (Reflected XSS on an admin page requires a logged-in user with access to that page).
  • Preconditions: The plugin must be active, and a victim must be tricked into clicking a specially crafted link.

3. Code Flow

Based on the vulnerability description, the expected code flow is:

  1. Entry Point: A user navigates to a URL such as /wp-admin/admin.php/index.php/"><script>alert(1)</script>/?page=product-icon-badge.
  2. Plugin Initialization: The plugin registers an admin menu (likely via add_menu_page or add_submenu_page) and a callback function to render the settings.
  3. Vulnerable Sink: Inside the settings callback function (often in a view file or a class method), the code contains a line similar to:
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?page=product-icon-badge">
    
  4. Reflection: Because $_SERVER['PHP_SELF'] is not wrapped in esc_url(), the browser interprets the path segment /"><script>alert(1)</script>/ as a breakout from the action attribute, injecting the <script> tag into the DOM.

4. Nonce Acquisition Strategy

Reflected XSS via PHP_SELF typically occurs during a GET request to render the page and does not require a nonce for the initial reflection.

However, if the objective is to escalate the XSS into a Cross-Site Request Forgery (CSRF) attack (e.g., to create a new admin user), the XSS payload itself can extract nonces directly from the page context using the browser_eval tool:

  1. Identify the target action (e.g., creating a user).
  2. The script running via XSS can fetch the relevant admin page (e.g., /wp-admin/user-new.php).
  3. Extract the nonce from the DOM:
    const nonce = document.querySelector('#_wpnonce_create-user')?.value;
    

5. Exploitation Strategy

Since the source is not provided, the following steps involve identifying the exact location of the sink:

Phase 1: Discovery

  1. Identify Admin Page: Use wp-cli to find the plugin's menu slug.
    grep -rn "add_menu_page\|add_submenu_page" /var/www/html/wp-content/plugins/product-icon-badge/
    
  2. Locate Sink: Search for PHP_SELF usage in the plugin directory.
    grep -rn "PHP_SELF" /var/www/html/wp-content/plugins/product-icon-badge/
    
    • Note: If PHP_SELF is found in a form action, this is the primary target.

Phase 2: Execution

  1. Construct Payload:
    Assuming the slug is product-icon-badge (inferred) and the sink is in the admin settings:
    URL: http://localhost:8080/wp-admin/admin.php/index.php/"><script>alert(document.domain)</script>/?page=product-icon-badge
  2. Trigger Reflection:
    Use the http_request tool (Playwright) to simulate an admin clicking the link.
    • Method: GET
    • URL: http://localhost:8080/wp-admin/admin.php/index.php/%22%3E%3Cscript%3Ealert(document.domain)%3C/script%3E/?page=product-icon-badge
    • Cookies: Must include valid admin session cookies.

6. Test Data Setup

  1. Install Plugin: Install "NS Product icon badge" version 1.2.4.
  2. Activate Plugin: wp plugin activate product-icon-badge.
  3. User Creation: Ensure an admin user exists (e.g., user: admin, pass: password).
  4. Admin Session: Log in as the admin via the browser to establish session cookies for the agent.

7. Expected Results

  • The HTTP response should contain the raw payload: <form action="/wp-admin/admin.php/index.php/"><script>alert(document.domain)</script>/...
  • In a browser context, an alert box displaying the domain name should appear.
  • The action attribute of the form will be broken, confirming the lack of esc_url().

8. Verification Steps

  1. Source Check: Use http_request and check if the string <script>alert(document.domain)</script> exists in the returned body without being encoded (i.e., not &lt;script&gt;).
  2. DOM Verification: Use browser_eval to check if a specific element or global variable was modified by the injected script.
    browser_eval("window.xss_verified = true;")
    

9. Alternative Approaches

  • Attribute Breakout: If the PHP_SELF variable is reflected inside a different HTML attribute (e.g., value or href), adjust the payload to use single quotes ' or double quotes " and event handlers:
    index.php/"onmouseover="alert(1)"
  • Bypass Filtering: If simple <script> tags are filtered, use an <img> tag with an onerror event:
    index.php/"><img src=x onerror=alert(1)>
  • JS Protocol: If reflected in an <a> tag's href:
    index.php/javascript:alert(1)// (Though this is less common for PHP_SELF which usually outputs paths).
Research Findings
Static analysis — not yet PoC-verified

Summary

The NS Product icon badge plugin for WordPress is vulnerable to Reflected Cross-Site Scripting (XSS) due to the unsafe use of the PHP_SELF server variable in its admin settings. An attacker can craft a URL containing a malicious script in the path segment, which is reflected into a form's action attribute without sanitization, leading to script execution in the context of an administrator's session.

Vulnerable Code

// Inferred from vulnerability description and common WordPress patterns
// likely located in the admin settings template or class

<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?page=product-icon-badge">
    <!-- Settings fields -->
</form>

Security Fix

--- a/product-icon-badge/admin/settings-page.php
+++ b/product-icon-badge/admin/settings-page.php
@@ -10,1 +10,1 @@
- <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?page=product-icon-badge">
+ <form method="post" action="<?php echo esc_url($_SERVER['PHP_SELF']); ?>?page=product-icon-badge">

Exploit Outline

The exploit targets the admin settings page of the plugin. An attacker crafts a URL that appends a script payload to the PHP script path (e.g., /wp-admin/admin.php/index.php/"><script>alert(1)</script>/?page=product-icon-badge). When an authenticated administrator clicks this link, the server echoes the malicious path directly into the 'action' attribute of an HTML form. This breaks the attribute context and injects the script into the DOM, where it executes. No nonces are required for the initial reflection as it occurs during a GET request.

Check if your site is affected.

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