SECURITY ADVISORY / 01

CVE-2026-3584 Exploit & Vulnerability Analysis

Complete CVE-2026-3584 security advisory with proof of concept (PoC), exploit details, and patch analysis for kali-forms.

kali-forms products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An unauthenticated attacker can inject arbitrary PHP callbacks into Kali Forms' placeholder processing pipeline by submitting crafted POST field names that override legitimate internal placeholder handlers.

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

form_id=1&{entryCounter}=system('id')&{thisPermalink}=phpinfo&submit=1

On vulnerable versions, the server processes these field names as placeholder keys. Because the code fails to restore the legitimate internal callable placeholders before returning, the attacker-supplied values replace the safe callback references. When the form processor later invokes call_user_func() on these placeholders, it executes the attacker's payload. The response will contain command output (if the callback produces output) or the attacker observes side effects such as files written to disk or database records modified by the injected function call.

What the Patch Did

Before:

foreach ($this->data as $key => $value) {
    $type = 'textbox';
    if (isset($this->field_type_map[$key]) && !empty($this->field_type_map[$key])) {
        $type = $this->field_type_map[$key];
    }
    $this->_run_placeholder_switch($type, $key, $value);
}

$this->placeholdered_data = apply_filters($this->slug . '_form_placeholders', $this->placeholdered_data);

return $data;

After:

if ($this->post !== null && empty($this->field_type_map)) {
    $prepared_maps            = $this->setup_field_map();
    $this->field_type_map     = $prepared_maps['map'];
    $this->advanced_field_map = $prepared_maps['advanced'];
}

foreach ($this->data as $key => $value) {
    if (!array_key_exists($key, $this->field_type_map)) {
        continue;
    }

    $type = 'textbox';
    if (!empty($this->field_type_map[$key])) {
        $type = $this->field_type_map[$key];
    }
    $this->_run_placeholder_switch($type, $key, $value);
}

$this->placeholdered_data = apply_filters($this->slug . '_form_placeholders', $this->placeholdered_data);

$this->restore_internal_callable_placeholders();

return $data;

The patch introduced two critical security controls. First, it added explicit field-map validation via array_key_exists() in the loop, ensuring that only fields registered in the form definition are processed—unknown POST keys are silently skipped. Second, and most importantly, it calls $this->restore_internal_callable_placeholders() immediately before returning, which overwrites the $this->placeholdered_data array with the legitimate internal callback references. This prevents user-supplied POST data from poisoning the placeholder handlers that call_user_func() will later invoke.

Root Cause

CWE-94: Improper Control of Generation of Code ('Code Injection') combined with CWE-471: Modification of Assumed-Immutable Data.

The prepare_post_data() function accepts user-supplied field names from $_POST and directly merges them into the $this->placeholdered_data array without sanitization or validation. Because the code uses generic key-matching (checking if a POST key exists), an attacker can submit field names identical to reserved internal placeholder keys like {entryCounter}, {thisPermalink}, or {submission_link}. These keys are expected to map to safe internal callback functions (such as WordPress core functions), but the code never restores or protects these mappings after filters run. When call_user_func() later processes the placeholders, it executes whatever callback string the attacker placed in the POST data, crossing the trust boundary between user input and executable code without any check.

Why It Works

The load-bearing line is $this->restore_internal_callable_placeholders();. Without it, the legitimate callback references stored in the placeholder array remain poisoned by user input. Removing this single call would leave the vulnerability fully exploitable—an attacker's injected callback would persist through to the call_user_func() sink.

The field-map validation (array_key_exists() check) is necessary but insufficient. It prevents processing of completely unknown field names, but an attacker could still craft field names matching legitimate form fields and exploit those—unless they were also constrained. The validation layer raises the bar for exploitation but only the placeholder restoration provides defense-in-depth: it guarantees that no matter what keys reach the placeholder dictionary, the dangerous keys always resolve to safe, immutable callbacks before they are invoked. The engineer added the field-map initialization check (setup_field_map() call) to ensure the map is populated early, preventing a race condition where an empty map would allow all keys to pass through.

Hardening Checklist

  • Whitelist field keys before processing: Use array_key_exists() or isset() against an explicit whitelist of expected form field names; reject all others. Do not rely on isset() alone, as it treats missing keys and null values identically (CWE-471).

  • Separate user data from callable references: Store form field values in one array and callback references in another, never in the same structure. Validate that the callback dictionary is always populated from a hard-coded or database source, not user input.

  • Restore immutable state before use in dynamic calls: Immediately before invoking call_user_func(), array_map(), or any function that uses user-touched data as a callback, reload the callback from a trusted source. Do not assume a single initialization is sufficient.

  • Use a callback registry pattern: Instead of storing callback strings in user-influenced arrays, maintain a separate registry mapping field names to closures or static class methods. Look up callbacks only in this registry.

  • Validate callback targets with is_callable(): Before invoking any user-derived callback, confirm it is callable and log the invocation. This will catch poisoned or malformed callbacks at runtime.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-3584

Frequently asked questions about CVE-2026-3584

What is CVE-2026-3584?

CVE-2026-3584 is a security vulnerability identified in kali-forms. 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-2026-3584?

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

How does CVE-2026-3584 get exploited?

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

What products and versions are affected by CVE-2026-3584?

CVE-2026-3584 affects kali-forms. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-3584?

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

What is the CVSS score for CVE-2026-3584?

The severity rating and CVSS scoring for CVE-2026-3584 affecting kali-forms is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.