[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$foYRKL5anXrgH2WlN3fo88zDw0-a2kzeBVPZSwwp1h4o":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":33},"CVE-2026-10096","qi-blocks-insecure-direct-object-reference-to-authenticated-author-arbitrary-style-modification-via-pageid-parameter","Qi Blocks \u003C= 1.4.9 - Insecure Direct Object Reference to Authenticated (Author+) Arbitrary Style Modification via 'page_id' Parameter","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.","qi-blocks",null,"\u003C=1.4.9","1.5.0","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Authorization Bypass Through User-Controlled Key","2026-06-30 19:07:13","2026-07-01 07:53:37",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F64251fd4-1627-49d0-831f-5cb9898c38bf?source=api-prod",1,[],"researched",false,3,"# Exploitation Research Plan: CVE-2026-10096 (Qi Blocks Style Modification IDOR)\n\n## 1. Vulnerability Summary\nThe **Qi Blocks** plugin (\u003C= 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.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** REST API Route (likely registered under the `qi-blocks\u002Fv1` namespace).\n- **HTTP Method:** `POST` (typically used for saving\u002Fupdating settings).\n- **Vulnerable Parameter:** `page_id` (used to determine which post or global setting to update).\n- **Authentication:** Authenticated, Author role or higher (requires `edit_posts` and `publish_posts` capabilities).\n- **Payload:** A JSON body containing the `page_id` of the target (e.g., an Administrator's post ID or the strings `'template'`\u002F`'widget'`) and the desired `qi_blocks_styles` data.\n\n## 3. Code Flow (Inferred)\n1. **Registration:** The plugin registers a REST route during `rest_api_init`.\n   - *Grep target:* `register_rest_route( 'qi-blocks\u002Fv1',`\n2. **Permission Check:** The `permission_callback` function likely looks like:\n   ```php\n   'permission_callback' => function() {\n       return current_user_can( 'edit_posts' ) && current_user_can( 'publish_posts' );\n   }\n   ```\n   *Note: This check is insufficient as it only verifies the user can edit **some** posts, not the specific post indicated by `page_id`.*\n3. **Execution:** The callback function (e.g., `save_styles_callback`) retrieves the `page_id` parameter.\n4. **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`.\n\n## 4. Nonce Acquisition Strategy\nREST API requests in WordPress require a `wp_rest` nonce for authenticated users to prevent CSRF.\n\n1. **User Role:** Authenticate as an **Author**.\n2. **Detection:** Qi Blocks likely enqueues its styles and scripts in the block editor (Gutenberg).\n3. **Execution:**\n   - Create a post as the Author: `wp post create --post_type=post --post_status=draft --post_author=[AUTHOR_ID]`.\n   - Navigate to the editor for that post in the browser.\n   - The `wp_rest` nonce is globally available in the `wpApiSettings` object in the browser context.\n4. **Browser Eval:**\n   ```javascript\n   \u002F\u002F Recommended approach to get the REST nonce\n   browser_eval(\"window.wpApiSettings?.nonce\")\n   ```\n\n## 5. Exploitation Strategy\nThe goal is to modify the styles of a page the Author does not own or to modify the site-wide 'template' styles.\n\n### Step 1: Discover Target IDs\n- Find a target page ID (e.g., Page ID 1, usually the \"Privacy Policy\" or \"Sample Page\" owned by Admin).\n- Target keywords: `template`, `widget`.\n\n### Step 2: Craft Payload\nThe payload must mimic a legitimate style save but point to the target ID.\n- **URL:** `http:\u002F\u002F[target]\u002Fwp-json\u002Fqi-blocks\u002Fv1\u002Fsave-styles` (inferred)\n- **Method:** `POST`\n- **Headers:**\n  - `Content-Type: application\u002Fjson`\n  - `X-WP-Nonce: [EXTRACTED_NONCE]`\n- **Body:**\n  ```json\n  {\n    \"page_id\": \"template\",\n    \"styles\": \"body { display: none !important; }\"\n  }\n  ```\n  *(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).*\n\n### Step 3: Execute Request\nUse the `http_request` tool to send the POST request from the authenticated Author session.\n\n## 6. Test Data Setup\n1. **Target Content:** Ensure a page exists owned by the Administrator (e.g., ID `2`).\n2. **Attacker User:**\n   ```bash\n   wp user create attacker attacker@example.com --role=author --user_pass=password123\n   ```\n3. **Plugin Activation:** Ensure Qi Blocks is active.\n\n## 7. Expected Results\n- The REST API should return a `200 OK` or `201 Created` response.\n- If `page_id` was set to a numeric ID, the `qi_blocks_styles` post meta for that ID will be updated.\n- If `page_id` was set to `template`, the global style option for Qi Blocks will be updated.\n- **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).\n\n## 8. Verification Steps\nAfter the HTTP request, verify the modification using WP-CLI:\n```bash\n# Check if post meta was changed for a specific post (replace ID)\nwp post meta get 2 qi_blocks_styles\n\n# Check if global options were changed\nwp option get qi_blocks_global_styles\n# (The exact option name should be verified via grep: \"update_option\")\n```\n\n## 9. Alternative Approaches\nIf the `save-styles` endpoint requires specific block identifiers:\n1. **Identify Block Params:** Capture a legitimate save request using the browser's Network tab while editing a post as the Author.\n2. **Replay with modification:** Replay that captured request but change the `page_id` to the target.\n3. **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.","The Qi Blocks plugin for WordPress (\u003C= 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.","\u002F\u002F Inferred from Research Plan Section 3: Permission Check\n'permission_callback' => function() {\n    return current_user_can( 'edit_posts' ) && current_user_can( 'publish_posts' );\n}\n\n---\n\n\u002F\u002F Inferred from Research Plan Section 3: Execution\u002FSink logic\n$page_id = $request->get_param( 'page_id' );\n\u002F\u002F ... logic follows to update based on page_id without ownership verification\nupdate_post_meta( $page_id, 'qi_blocks_styles', $styles );\n\u002F\u002F or for reserved keywords\nupdate_option( 'qi_blocks_global_styles', $styles );","--- a\u002Finc\u002Frest\u002Fclass-qi-blocks-rest-api.php\n+++ b\u002Finc\u002Frest\u002Fclass-qi-blocks-rest-api.php\n@@ -10,5 +10,12 @@\n-    'permission_callback' => function() {\n-        return current_user_can( 'edit_posts' ) && current_user_can( 'publish_posts' );\n-    }\n+    'permission_callback' => function( $request ) {\n+        $page_id = $request->get_param( 'page_id' );\n+        if ( is_numeric( $page_id ) ) {\n+            return current_user_can( 'edit_post', $page_id );\n+        }\n+        if ( in_array( $page_id, array( 'template', 'widget' ), true ) ) {\n+            return current_user_can( 'edit_theme_options' );\n+        }\n+        return false;\n+    }","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., \u002Fwp-json\u002Fqi-blocks\u002Fv1\u002Fsave-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.","gemini-3-flash-preview","2026-07-25 12:41:42","2026-07-25 12:42:16",{"type":34,"vulnerable_version":35,"fixed_version":9,"vulnerable_browse":36,"vulnerable_zip":37,"fixed_browse":9,"fixed_zip":9,"all_tags":38},"plugin","1.4.9","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fqi-blocks\u002Ftags\u002F1.4.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fqi-blocks.1.4.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fqi-blocks\u002Ftags"]