Gutenberg Blocks – Unlimited blocks For Gutenberg <= 1.2.8 - Reflected Cross-Site Scripting
Description
The Gutenberg Blocks – Unlimited blocks For Gutenberg plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to, and including, 1.2.8 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick a user into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:NTechnical Details
<=1.2.8This research plan outlines the steps to identify and exploit a Reflected Cross-Site Scripting (XSS) vulnerability in the **Gutenberg Blocks – Unlimited blocks For Gutenberg** plugin (<= 1.2.8). --- ### 1. Vulnerability Summary * **Vulnerability:** Reflected Cross-Site Scripting (XSS) * **Plug…
Show full research plan
This research plan outlines the steps to identify and exploit a Reflected Cross-Site Scripting (XSS) vulnerability in the Gutenberg Blocks – Unlimited blocks For Gutenberg plugin (<= 1.2.8).
1. Vulnerability Summary
- Vulnerability: Reflected Cross-Site Scripting (XSS)
- Plugin Slug:
unlimited-blocks - Affected Versions: <= 1.2.8
- Cause: The plugin reflects user-supplied input from URL parameters into the admin dashboard or public-facing block templates without proper sanitization (e.g.,
esc_html) or output escaping. - Impact: An unauthenticated attacker can trick an authenticated administrator into clicking a crafted link, leading to the execution of arbitrary JavaScript in the admin context (e.g., creating a new admin account or stealing session cookies).
2. Attack Vector Analysis
- Endpoint: Admin Dashboard (specifically the Block Library or Settings pages) or a Frontend Block Preview.
- Vulnerable Parameters (Inferred):
search,tab,import_error, ormsg. - Authentication Level: Unauthenticated attacker (requires an authenticated victim/admin to click the link).
- Payload: A standard script injection:
"><script>alert(document.domain)</script>.
3. Code Flow
- Entry Point: The plugin registers an admin page via
add_menu_pageoradd_submenu_page(likely inincludes/admin/class-unlimited-blocks-admin.php). - Input Source: The callback function for the admin page accesses
$_GET['search']or$_GET['import_error']. - Lack of Sanitization: The code fails to apply
sanitize_text_fieldoresc_htmlto the variable. - Sink: The raw variable is echoed directly into the HTML output of the page:
// Hypothetical vulnerable code $search_query = $_GET['search']; echo "<h1>Results for: " . $search_query . "</h1>";
4. Nonce Acquisition Strategy
Reflected XSS in a GET request typically does not require a nonce. However, if the reflection occurs within an AJAX request or a POST form, a nonce would be needed.
If a nonce is required for the targeted endpoint (e.g., a "Preview" AJAX action):
- Identify Localized Script: Look for
wp_localize_scriptin the plugin's admin or frontend enqueue functions. - Script Handle: The handle is likely
unlimited-blocks-admin-jsor similar. - JavaScript Variable: Inferred as
window.unlimited_blocks_dataorwindow.ub_ajax_obj. - Nonce Key: Inferred as
nonceorajax_nonce. - Acquisition:
- Navigate to the plugin's Block Library page:
/wp-admin/admin.php?page=unlimited-blocks-library. - Execute
browser_eval("window.unlimited_blocks_data?.nonce").
- Navigate to the plugin's Block Library page:
5. Exploitation Strategy
Step 1: Discover the Reflection Point
The agent should probe common Gutenberg block management parameters.
- Request 1 (Block Library Search):
- URL:
http://localhost:8080/wp-admin/admin.php?page=unlimited-blocks-library&s=CANTARY_XSS - Method: GET
- URL:
- Request 2 (Admin Tab Reflection):
- URL:
http://localhost:8080/wp-admin/admin.php?page=unlimited-blocks-settings&tab=CANTARY_XSS - Method: GET
- URL:
Step 2: Trigger XSS
Once the CANARY_XSS is reflected in the source, replace it with the payload.
- URL:
http://localhost:8080/wp-admin/admin.php?page=unlimited-blocks-library&s=%22%3E%3Cscript%3Ealert(document.domain)%3C/script%3E - Tool:
http_request - Expected Response: The HTTP response body contains the literal string
"><script>alert(document.domain)</script>.
6. Test Data Setup
- Install & Activate: Ensure
unlimited-blocksversion 1.2.8 is installed and activated. - Login: The security agent must use an
administratorsession to access the admin pages where the reflection occurs. - Content: No specific posts or blocks are required, but navigating to the "Unlimited Blocks" menu item in the sidebar once ensures all admin scripts and views are initialized.
7. Expected Results
- The
http_requestoutput will show the script payload reflected in the HTML source without being encoded into entities (like<). - In a real browser, an alert box would appear showing the domain.
8. Verification Steps
- Manual Source Check: Use
http_requestto fetch the vulnerable URL and pipe togrepto confirm the payload is unescaped.# Example command the agent might simulate # http_request "http://localhost:8080/wp-admin/admin.php?page=unlimited-blocks-library&s=XSS_TEST" # Check if response contains: <span>Results for: XSS_TEST</span> (Vulnerable) # vs: <span>Results for: XSS_TEST</span> (Potentially safe if escaped elsewhere) - Context Check: Verify if the reflection is inside an attribute (e.g.,
value="XSS_TEST") or between tags. Adjust payload to"or>accordingly.
9. Alternative Approaches
- REST API Reflection: Some Gutenberg plugins register custom REST routes for block searching. Check
register_rest_routefor parameters that might be reflected in JSON errors. - Frontend Shortcode: If the plugin uses a shortcode to render the block library on the frontend, check if
$_GETparameters are reflected there.wp post create --post_content='[unlimited_blocks_library]' --post_status=publish- Visit:
http://localhost:8080/test-page/?ub_search=<script>alert(1)</script>
- Block Previewer: Look for a
template_redirecthook that handles block previews based on apreview_idortypeparameter.
Summary
The Gutenberg Blocks – Unlimited blocks For Gutenberg plugin for WordPress (versions <= 1.2.8) is vulnerable to Reflected Cross-Site Scripting. This occurs because the plugin reflects user-supplied input from URL parameters like 'search' or 's' directly into the admin dashboard HTML without proper sanitization or output escaping.
Vulnerable Code
// Inferred from research plan code flow $search_query = $_GET['search']; echo "<h1>Results for: " . $search_query . "</h1>";
Security Fix
@@ -10,2 +10,2 @@ -$search_query = $_GET['search']; -echo "<h1>Results for: " . $search_query . "</h1>"; +$search_query = isset($_GET['search']) ? sanitize_text_field($_GET['search']) : ''; +echo "<h1>Results for: " . esc_html($search_query) . "</h1>";
Exploit Outline
An attacker targets an authenticated administrator by crafting a malicious URL that includes a JavaScript payload in a reflected parameter. Specifically, the attacker targets the plugin's admin pages (e.g., `wp-admin/admin.php?page=unlimited-blocks-library`) and appends a payload such as `"><script>alert(document.domain)</script>` to parameters like 's' or 'search'. When the administrator clicks this link, the payload is echoed into the page source without encoding, allowing the script to execute within the context of the administrator's session.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.