CVE-2026-57724

Kirki – Freeform Page Builder, Website Builder & Customizer <= 6.0.12 - Unauthenticated PHP Object Injection

highDeserialization of Untrusted Data
8.1
CVSS Score
8.1
CVSS Score
high
Severity
6.0.13
Patched in
9d
Time to patch

Description

The Kirki – Freeform Page Builder, Website Builder & Customizer plugin for WordPress is vulnerable to PHP Object Injection in versions up to, and including, 6.0.12 via deserialization of untrusted input. This makes it possible for unauthenticated attackers to inject a PHP Object. No known POP chain is present in the vulnerable software. If a POP chain is present via an additional plugin or theme installed on the target system, it could allow the attacker to delete arbitrary files, retrieve sensitive data, or execute code.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=6.0.12
PublishedJuly 6, 2026
Last updatedJuly 14, 2026
Affected pluginkirki

What Changed in the Fix

Changes introduced in v6.0.13

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on identifying and exploiting the **Unauthenticated PHP Object Injection** vulnerability in the **Kirki – Freeform Page Builder** plugin (CVE-2026-57724). ### 1. Vulnerability Summary The vulnerability exists in versions of the Kirki plugin up to and including **6.0.12**.…

Show full research plan

This research plan focuses on identifying and exploiting the Unauthenticated PHP Object Injection vulnerability in the Kirki – Freeform Page Builder plugin (CVE-2026-57724).

1. Vulnerability Summary

The vulnerability exists in versions of the Kirki plugin up to and including 6.0.12. It is a PHP Object Injection vulnerability caused by the insecure use of unserialize() (or its wrapper maybe_unserialize()) on untrusted input. Because the input can be supplied by an unauthenticated user, an attacker can inject arbitrary PHP objects. If a suitable POP (Property Oriented Programming) chain exists in the WordPress environment (via other plugins or the theme), this can lead to remote code execution, file deletion, or sensitive data retrieval.

2. Attack Vector Analysis

  • Endpoint: Likely an AJAX action via admin-ajax.php or a REST API endpoint registered in includes/API.php via FrontendApi::register().
  • Vulnerable Action: Based on the provided JS files, kirki_post_apis is a primary suspect. However, an "unauthenticated" vulnerability typically involves an action registered with the wp_ajax_nopriv_ prefix or a REST route with a permission_callback that returns true.
  • Payload Parameter: Common parameters in Kirki for such data include kirki_data, data, settings, or config.
  • Authentication: None required (Unauthenticated).
  • Complexity: High (requires a POP chain not present in Kirki itself).

3. Code Flow

  1. Entry Point: An unauthenticated request is sent to admin-ajax.php?action=kirki_... or a REST route like /wp-json/kirki/v1/....
  2. Hook: The action is handled by a method in a class like Kirki\API\PostApis or Kirki\API\Frontend\FrontendApi.
  3. Input Source: The code retrieves a parameter from $_POST or $_GET.
  4. The Sink: The code calls unserialize() or maybe_unserialize() on this input without prior validation or signature checking.
  5. Injection: The PHP engine instantiates the injected object, triggering magic methods (__wakeup, __destruct, __toString).

4. Nonce Acquisition Strategy

While the vulnerability is labeled "Unauthenticated," some handlers may still attempt a nonce check that is bypassable or improperly implemented for logged-out users.

  • Suspected Nonce Variable: window.kirki_admin?.nonce (found in assets/js/admin/custom-link-in-toolbar.js).
  • Acquisition Method:
    1. The kirki_admin object is likely localized on post editing pages or pages where the Kirki editor is active.
    2. Check if any public-facing page (e.g., a page containing a Kirki block or shortcode) enqueues the script and localizes the nonce.
    3. Action: Use browser_navigate to the homepage or a Kirki-built page.
    4. Extraction: browser_eval("window.kirki_admin?.nonce").
  • Bypass Check: Verify if the backend handler for the nopriv action actually calls check_ajax_referer or wp_verify_nonce. If the action is truly unauthenticated, it may omit this check entirely.

5. Exploitation Strategy

Since Kirki lacks a built-in POP chain, the PoC will focus on demonstrating the injection.

  1. Locate Sink:
    • Search the plugin directory for unserialize or maybe_unserialize.
    • grep -rP "unserialize\s*\(\s*\\$(?:_GET|_POST|_REQUEST|data|config|settings)" .
  2. Identify Endpoint:
    • Trace the sink back to an add_action('wp_ajax_nopriv_...', ...) or register_rest_route.
  3. Prepare Payload:
    • Construct a dummy object to prove injection (e.g., O:8:"stdClass":1:{s:3:"poc";s:7:"success";}).
    • Base64 encode the payload if the code expects it: Tzo4OiJzdGRDbGFzcyI6MTp7czozOiJwb2MiO3M6Nzoic3VjY2VzcyI7fQ==.
  4. Send Request:
    # Example AJAX request
    http_request POST "http://localhost:8080/wp-admin/admin-ajax.php" \
      --data "action=kirki_vulnerable_action&data=PAYLOAD_HERE" \
      --header "Content-Type: application
    
Research Findings
Static analysis — not yet PoC-verified

Summary

The Kirki plugin for WordPress is vulnerable to Unauthenticated PHP Object Injection in versions up to 6.0.12 due to the insecure use of deserialization functions on untrusted user input. By sending a crafted POST request to an unauthenticated API endpoint, an attacker can inject arbitrary PHP objects, potentially leading to remote code execution or file manipulation if a suitable POP chain exists in the environment.

Vulnerable Code

// includes/API.php line 47-53
	public function register_api() {
		// Media apis.
		$media = new Media();
		$media->register_routes();

		$content_manager = new ContentManagerRest();
		$content_manager->register_routes();

		$kirki_comments = new KirkiCommentsRest();
		$kirki_comments->register_routes();

		FrontendApi::register();
	}

---

// The vulnerability occurs in the handlers registered by FrontendApi::register() or similar AJAX actions.
// These handlers process user-supplied parameters (such as 'data' or 'settings') using maybe_unserialize() without validation.
// Example of the vulnerable pattern suspected in the underlying handlers:
// $settings = maybe_unserialize( $_POST['data'] );

Security Fix

Only in /home/deploy/wp-safety.org/data/plugin-versions/kirki/6.0.13: app
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/kirki/6.0.12/assets/css/kirki-editor.min.css /home/deploy/wp-safety.org/data/plugin-versions/kirki/6.0.13/assets/css/kirki-editor.min.css
--- /home/deploy/wp-safety.org/data/plugin-versions/kirki/6.0.12/assets/css/kirki-editor.min.css	2026-06-24 12:03:12.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/kirki/6.0.13/assets/css/kirki-editor.min.css	2026-07-03 11:43:06.000000000 +0000
@@ -1 +1 @@
-@font-face{font-display:swap;font-family:Inter;font-style:normal;font-weight:400;src:url(../../fonts/Inter-Regular.woff) format("woff")}@font-face{font-display:swap;font-family:Inter;font-style:normal;font-weight:700;src:url(../../fonts/Inter-Bold.woff) format("woff")}... (truncated)

Exploit Outline

1. Identify the target WordPress installation running Kirki version 6.0.12 or earlier. 2. Locate an unauthenticated endpoint registered by the plugin, such as a REST API route under '/wp-json/kirki/v1/' or an AJAX action like 'kirki_post_apis' that processes serialized input. 3. Identify a suitable PHP Object Injection (POP) chain present in the WordPress environment (e.g., from other plugins or the active theme). 4. Prepare a payload containing the serialized POP chain object, potentially Base64 encoding it if required by the specific handler. 5. Send a POST request to the identified endpoint with the payload in the expected parameter (e.g., 'data', 'settings', or 'config'). 6. The server's call to maybe_unserialize() on the malicious input will instantiate the object and trigger its magic methods (e.g., __wakeup, __destruct), leading to the execution of the POP chain.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.