NS Product icon badge <= 1.2.4 - Reflected Cross-Site Scripting via PHP_SELF
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:NTechnical Details
<=1.2.4# 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:
- Entry Point: A user navigates to a URL such as
/wp-admin/admin.php/index.php/"><script>alert(1)</script>/?page=product-icon-badge. - Plugin Initialization: The plugin registers an admin menu (likely via
add_menu_pageoradd_submenu_page) and a callback function to render the settings. - 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"> - Reflection: Because
$_SERVER['PHP_SELF']is not wrapped inesc_url(), the browser interprets the path segment/"><script>alert(1)</script>/as a breakout from theactionattribute, 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:
- Identify the target action (e.g., creating a user).
- The script running via XSS can fetch the relevant admin page (e.g.,
/wp-admin/user-new.php). - 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
- Identify Admin Page: Use
wp-clito find the plugin's menu slug.grep -rn "add_menu_page\|add_submenu_page" /var/www/html/wp-content/plugins/product-icon-badge/ - Locate Sink: Search for
PHP_SELFusage in the plugin directory.grep -rn "PHP_SELF" /var/www/html/wp-content/plugins/product-icon-badge/- Note: If
PHP_SELFis found in a form action, this is the primary target.
- Note: If
Phase 2: Execution
- Construct Payload:
Assuming the slug isproduct-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 - Trigger Reflection:
Use thehttp_requesttool (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.
- Method:
6. Test Data Setup
- Install Plugin: Install "NS Product icon badge" version 1.2.4.
- Activate Plugin:
wp plugin activate product-icon-badge. - User Creation: Ensure an admin user exists (e.g., user:
admin, pass:password). - 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
actionattribute of the form will be broken, confirming the lack ofesc_url().
8. Verification Steps
- Source Check: Use
http_requestand check if the string<script>alert(document.domain)</script>exists in the returned body without being encoded (i.e., not<script>). - DOM Verification: Use
browser_evalto 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_SELFvariable is reflected inside a different HTML attribute (e.g.,valueorhref), 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 anonerrorevent:index.php/"><img src=x onerror=alert(1)> - JS Protocol: If reflected in an
<a>tag'shref:index.php/javascript:alert(1)//(Though this is less common forPHP_SELFwhich usually outputs paths).
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
@@ -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.