Qi Blocks <= 1.4.9 - Insecure Direct Object Reference to Authenticated (Author+) Arbitrary Style Modification via 'page_id' Parameter
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:NTechnical Details
Source Code
WordPress.org SVNPatched version not available.
# 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/v1namespace). - 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_postsandpublish_postscapabilities). - Payload: A JSON body containing the
page_idof the target (e.g., an Administrator's post ID or the strings'template'/'widget') and the desiredqi_blocks_stylesdata.
3. Code Flow (Inferred)
- Registration: The plugin registers a REST route during
rest_api_init.- Grep target:
register_rest_route( 'qi-blocks/v1',
- Grep target:
- Permission Check: The
permission_callbackfunction likely looks like:
Note: This check is insufficient as it only verifies the user can edit some posts, not the specific post indicated by'permission_callback' => function() { return current_user_can( 'edit_posts' ) && current_user_can( 'publish_posts' ); }page_id. - Execution: The callback function (e.g.,
save_styles_callback) retrieves thepage_idparameter. - Sink: The code updates post meta (if
page_idis numeric) or a global WordPress option (ifpage_idis'template') usingupdate_post_meta()orupdate_option(), without verifying that the$current_useris 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.
- User Role: Authenticate as an Author.
- Detection: Qi Blocks likely enqueues its styles and scripts in the block editor (Gutenberg).
- 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_restnonce is globally available in thewpApiSettingsobject in the browser context.
- Create a post as the Author:
- 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/jsonX-WP-Nonce: [EXTRACTED_NONCE]
- Body:
(Note: The exact key for styles might be{ "page_id": "template", "styles": "body { display: none !important; }" }qi_blocks_stylesorstyles. The agent should grep the source forget_paramin 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
- Target Content: Ensure a page exists owned by the Administrator (e.g., ID
2). - Attacker User:
wp user create attacker attacker@example.com --role=author --user_pass=password123 - Plugin Activation: Ensure Qi Blocks is active.
7. Expected Results
- The REST API should return a
200 OKor201 Createdresponse. - If
page_idwas set to a numeric ID, theqi_blocks_stylespost meta for that ID will be updated. - If
page_idwas set totemplate, the global style option for Qi Blocks will be updated. - Frontend Impact: Navigating to the target page (or any page if
templatewas targeted) will show the injected styles (e.g., a blank page ifdisplay: nonewas 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:
- Identify Block Params: Capture a legitimate save request using the browser's Network tab while editing a post as the Author.
- Replay with modification: Replay that captured request but change the
page_idto the target. - Target Options: If post meta modification fails, focus on the
templatekeyword, which likely maps to awp_optionsentry, affecting the entire site's layout.
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
@@ -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.