Kirki – Freeform Page Builder, Website Builder & Customizer <= 6.0.12 - Unauthenticated PHP Object Injection
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:HTechnical Details
What Changed in the Fix
Changes introduced in v6.0.13
Source Code
WordPress.org SVNThis 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.phpor a REST API endpoint registered inincludes/API.phpviaFrontendApi::register(). - Vulnerable Action: Based on the provided JS files,
kirki_post_apisis a primary suspect. However, an "unauthenticated" vulnerability typically involves an action registered with thewp_ajax_nopriv_prefix or a REST route with apermission_callbackthat returnstrue. - Payload Parameter: Common parameters in Kirki for such data include
kirki_data,data,settings, orconfig. - Authentication: None required (Unauthenticated).
- Complexity: High (requires a POP chain not present in Kirki itself).
3. Code Flow
- Entry Point: An unauthenticated request is sent to
admin-ajax.php?action=kirki_...or a REST route like/wp-json/kirki/v1/.... - Hook: The action is handled by a method in a class like
Kirki\API\PostApisorKirki\API\Frontend\FrontendApi. - Input Source: The code retrieves a parameter from
$_POSTor$_GET. - The Sink: The code calls
unserialize()ormaybe_unserialize()on this input without prior validation or signature checking. - 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 inassets/js/admin/custom-link-in-toolbar.js). - Acquisition Method:
- The
kirki_adminobject is likely localized on post editing pages or pages where the Kirki editor is active. - Check if any public-facing page (e.g., a page containing a Kirki block or shortcode) enqueues the script and localizes the nonce.
- Action: Use
browser_navigateto the homepage or a Kirki-built page. - Extraction:
browser_eval("window.kirki_admin?.nonce").
- The
- Bypass Check: Verify if the backend handler for the
noprivaction actually callscheck_ajax_refererorwp_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.
- Locate Sink:
- Search the plugin directory for
unserializeormaybe_unserialize. grep -rP "unserialize\s*\(\s*\\$(?:_GET|_POST|_REQUEST|data|config|settings)" .
- Search the plugin directory for
- Identify Endpoint:
- Trace the sink back to an
add_action('wp_ajax_nopriv_...', ...)orregister_rest_route.
- Trace the sink back to an
- 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==.
- Construct a dummy object to prove injection (e.g.,
- 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
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 @@ -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.