Peter's Date Countdown <= 2.0.0 - Reflected Cross-Site Scripting via $_SERVER['PHP_SELF']
Description
The Peter's Date Countdown plugin for WordPress is vulnerable to Reflected Cross-Site Scripting via the `$_SERVER['PHP_SELF']` parameter in all versions up to, and including, 2.0.0 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
<=2.0.0This plan outlines the research and exploitation strategy for **CVE-2026-1654**, a reflected Cross-Site Scripting (XSS) vulnerability in the "Peter's Date Countdown" plugin for WordPress. ### 1. Vulnerability Summary The **Peter's Date Countdown** plugin (versions <= 2.0.0) fails to sanitize or esc…
Show full research plan
This plan outlines the research and exploitation strategy for CVE-2026-1654, a reflected Cross-Site Scripting (XSS) vulnerability in the "Peter's Date Countdown" plugin for WordPress.
1. Vulnerability Summary
The Peter's Date Countdown plugin (versions <= 2.0.0) fails to sanitize or escape the $_SERVER['PHP_SELF'] superglobal before echoing it into the HTML response. PHP_SELF contains the path to the currently executing script relative to the document root. By appending arbitrary characters and script tags to the URL path (path-info), an attacker can inject malicious HTML/JavaScript that the browser will execute when the page is rendered.
2. Attack Vector Analysis
- Endpoint: Any page where the plugin renders a form or link using
PHP_SELF. This is most commonly found in the plugin's admin settings page. - Vulnerable Parameter: The URL path itself (interpreted as
PHP_SELF). - Authentication: Unauthenticated (Attacker), but requires a logged-in user with access to the vulnerable page (Victim, typically an Administrator) to click a crafted link.
- Preconditions: The plugin must be active. The victim must be tricked into visiting a URL containing the payload.
3. Code Flow (Inferred)
- Entry Point: A user (victim) navigates to an admin page registered by the plugin, e.g.,
wp-admin/options-general.php?page=peters-date-countdown. - Processing: The plugin's admin menu callback function is triggered.
- Vulnerable Sink: Inside the callback, the code likely contains a form or a self-referencing link:
// Example of vulnerable pattern echo '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?page=peters-date-countdown">'; - Reflection: Because
$_SERVER['PHP_SELF']includes the path provided in the URL (including everything after.php), the attacker-supplied script is echoed directly into theactionattribute without being wrapped inesc_url()oresc_attr().
4. Nonce Acquisition Strategy
Reflected XSS via PHP_SELF typically occurs during a GET request to display a page.
- Is a nonce required? No. The vulnerability exists in the rendering of the page, not in the processing of a state-changing request (like an AJAX action).
- Bypass: Since the goal is to execute JavaScript in the victim's browser, the lack of a nonce does not prevent the XSS from triggering.
5. Exploitation Strategy
The goal is to demonstrate that an unauthenticated attacker can execute JavaScript in the context of an administrator.
- Identify the Admin Page: Confirm the slug for the settings page. Based on standard WordPress conventions for this plugin, it is likely
peters-date-countdown. - Craft the Payload:
- We need to "break out" of the HTML attribute where
PHP_SELFis reflected. - If reflected in a form action:
action="/wp-admin/options-general.php/[PAYLOAD]?page=..." - Payload:
"><script>alert(document.domain)</script> - URL Encoded:
%22%3E%3Cscript%3Ealert(document.domain)%3C/script%3E
- We need to "break out" of the HTML attribute where
- Construct the Exploit URL:
http://TARGET/wp-admin/options-general.php/%22%3E%3Cscript%3Ealert(document.domain)%3C/script%3E?page=peters-date-countdown - Execution:
- Use
browser_navigateto simulate an administrator visiting the malicious URL. - The agent must be logged in as an admin in the browser session.
- Use
6. Test Data Setup
- Install Plugin: Use WP-CLI to install the vulnerable version.
wp plugin install peters-date-countdown --version=2.0.0 --activate - Create Admin: Ensure an administrator user exists (default
admin/password). - Identify Vulnerable File: Run a search to confirm the sink location.
grep -rn "PHP_SELF" /var/www/html/wp-content/plugins/peters-date-countdown/
7. Expected Results
- The browser should navigate to the URL.
- The HTML source of the rendered page should contain:
<form ... action="/wp-admin/options-general.php/"><script>alert(document.domain)</script>?page=peters-date-countdown" ...> - The
browser_evalor a screenshot should confirm the execution of thealert()or the presence of the injected script tag in the DOM.
8. Verification Steps
- Check for Reflection:
Usehttp_requestas an admin and check the body for the payload.// Example Verification Request const response = await http_request.get("http://localhost:8888/wp-admin/options-general.php/%22%3E%3Ccanary%3E?page=peters-date-countdown"); if (response.body.includes('"><canary>')) { console.log("Vulnerability Confirmed: Unescaped PHP_SELF reflection found."); } - Verify via CLI:
Confirm the plugin version is exactly 2.0.0.wp plugin get peters-date-countdown --field=version
9. Alternative Approaches
If the reflection is not in the action attribute of a form, check for:
- Hidden Inputs:
<input type="hidden" name="redirect" value="<?php echo $_SERVER['PHP_SELF']; ?>">- Payload:
"/><script>alert(1)</script>
- Payload:
- Anchor Tags:
<a href="<?php echo $_SERVER['PHP_SELF']; ?>">- Payload:
"><script>alert(1)</script>
- Payload:
- JS Variables:
var current_url = '<?php echo $_SERVER['PHP_SELF']; ?>';- Payload:
';alert(1);//
- Payload:
If options-general.php is not the parent page, search for add_menu_page or add_options_page in the source to find the correct parent file. (Common parents: admin.php, index.php, plugins.php).
Summary
The Peter's Date Countdown plugin for WordPress is vulnerable to reflected cross-site scripting (XSS) via the $_SERVER['PHP_SELF'] superglobal. This occurs because the plugin fails to sanitize or escape the URL path info before echoing it into the HTML output, allowing an attacker to execute arbitrary scripts in a user's browser via a crafted link.
Vulnerable Code
// Inferred from research plan section 3 // Any admin-facing file where forms or links are generated using PHP_SELF echo '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?page=peters-date-countdown'>";
Security Fix
@@ -130,1 +130,1 @@ - echo '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?page=peters-date-countdown">'; + echo '<form method="post" action="' . esc_url($_SERVER['PHP_SELF']) . '?page=peters-date-countdown">';
Exploit Outline
The exploit targets the way WordPress admin scripts process the URL path when $_SERVER['PHP_SELF'] is used to generate form actions. An attacker constructs a URL pointing to the plugin's settings page (e.g., options-general.php) but appends an XSS payload to the path itself. For example: /wp-admin/options-general.php/\"><script>alert(1)</script>?page=peters-date-countdown. When an authenticated administrator visits this link, the server-side code echoes the malicious script into the 'action' attribute of an HTML form. Because the output is not escaped with esc_url(), the browser parses the payload and executes the JavaScript in the context of the administrator's session.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.