SECURITY ADVISORY / 01

CVE-2025-66533 Exploit & Vulnerability Analysis

Complete CVE-2025-66533 security advisory with proof of concept (PoC), exploit details, and patch analysis.

cve_patchdiff:give NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An unauthenticated attacker can inject WordPress shortcodes into donor names stored in the GiveWP database, which are then executed server-side when the donor wall or campaign donations block is rendered to any site visitor.

Store the payload by submitting a donation with a malicious donor name:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.wordpress.local
Content-Type: application/x-www-form-urlencoded

action=give_process_donation&donorName=[do_shortcode_injection_here]&donation_amount=10&[email protected]

Trigger execution by visiting any page that displays the donor wall or campaign donations block:

curl http://target.wordpress.local/campaigns/fundraiser-page/

The response body will contain the executed shortcode output embedded in the <strong> tag where the donor name should appear. If the attacker uses a shortcode like [site_url] or a custom plugin shortcode, the result renders in the page markup visible to all visitors. More critically, if a malicious shortcode exists on the site (injected via another plugin or custom code), the attacker can trigger arbitrary PHP execution.

What the Patch Did

Before

$html = ob_get_clean();

// Return only donor html.
if (
'<strong>' . esc_html(!$donation->isAnonymous ? $donation->donorName : __('Anonymous', 'give')) . '</strong>',

After

$html = ob_get_clean();

// Strip shortcodes to prevent execution of user-supplied shortcode syntax.
$html = strip_shortcodes($html);

// Return only donor html.
if (
'<strong>' . esc_html(!$donation->isAnonymous ? strip_shortcodes($donation->donorName) : __('Anonymous', 'give')) . '</strong>',

The patch adds two calls to WordPress's strip_shortcodes() function. In the donor wall output handler (class-give-donor-wall.php line 151), strip_shortcodes() is applied to the entire buffer before return. In the campaign donations block template (render.php line 93), it is applied directly to $donation->donorName prior to HTML escaping. The strip_shortcodes() function removes all shortcode syntax (anything matching [shortcode_name ... ] pattern) from a string without rendering it, preventing the WordPress do_shortcode pipeline from ever encountering the attacker's input.

Root Cause

CWE-94: Improper Control of Generation of Code ('Code Injection') — specifically, unsafe shortcode execution.

The donor name field accepts user input at the point of donation submission. This value is stored unfiltered in the database. When the donor wall or campaign donations block renders, the plugin calls WordPress rendering functions that eventually invoke do_shortcode() on output containing the donor name. WordPress's do_shortcode() function parses and executes all shortcode tags in its input. Because the plugin never called strip_shortcodes() before passing donor data to rendering contexts, any shortcode syntax in the donor name (e.g., [wp_mail_smtp_get_current_user] or custom plugin shortcodes) was executed in the rendering phase, crossing the trust boundary from user-supplied stored data into executable code.

Why It Works

The single load-bearing line is strip_shortcodes($html) in the donor wall buffer handler and strip_shortcodes($donation->donorName) in the campaign block. If either were removed, the bug remains fully exploitable — an attacker's shortcode injection still reaches the output and is still parsed by do_shortcode(). The subsequent esc_html() call does not prevent shortcode execution; it only HTML-encodes the characters after shortcodes are already processed. A shortcode like [my_malicious_function] would be stripped to an empty string before esc_html() ever sees it. Without strip_shortcodes(), esc_html('[my_malicious_function]') outputs the literal string &lsqb;my_malicious_function&rsqb;, which looks safe in HTML but still triggers shortcode parsing earlier in the rendering pipeline. This is why the engineer added strip_shortcodes() at both locations: belt and suspenders defense ensures that no code path bypasses the removal, whether the output goes through the donor wall template or the campaign block template.

Hardening Checklist

  • Audit all user-input sinks for do_shortcode() calls: Use wp-cli plugin search-replace or grep to find every call to do_shortcode(), apply_filters() with shortcode-aware callbacks, and template rendering functions. For each, trace back to confirm the input has been explicitly stripped via strip_shortcodes() or restricted to safe sources (e.g., post content created by admins only).

  • Apply strip_shortcodes() to all user-supplied fields before rendering: Treat donor names, testimonials, custom form fields, and any user-editable text as untrusted. Call strip_shortcodes() immediately before output escaping (esc_html(), esc_attr()), not as an afterthought in a central template.

  • Implement capability checks on donation form submission: Require current_user_can('manage_options') or a custom capability for users who can edit their own donor name post-submission, and sanitize those edits with sanitize_text_field() followed by strip_shortcodes().

  • Test shortcode injection in your test suite: Add a unit test that submits a donation with donor name [do_shortcode] or [site_url] and asserts that the rendered output does not contain the shortcode's result or any executable syntax.

  • Use wp_kses_post() for rich text fields only: If donor names or testimonials genuinely need to support limited HTML, use wp_kses_post() which has a whitelist of safe tags — but still call strip_shortcodes() first to be explicit about rejecting code injection vectors.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2025-66533

Frequently asked questions about CVE-2025-66533

What is CVE-2025-66533?

CVE-2025-66533 is a security vulnerability. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2025-66533?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2025-66533. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2025-66533 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2025-66533?

CVE-2025-66533 — check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2025-66533?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls.

What is the CVSS score for CVE-2025-66533?

The severity rating and CVSS scoring for CVE-2025-66533 is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.