Static Block <= 2.2 - Insecure Direct Object Reference to Authenticated (Contributor+) Sensitive Information Disclosure via Shortcode 'id' Attribute
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:NTechnical Details
# 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
idattribute within the[static_block_content id="X"]shortcode. - Authentication Level: Contributor+. Contributors have the
edit_postscapability, allowing them to create posts and include shortcodes, but they lack theread_private_postscapability 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
- Registration: The plugin registers the shortcode in the main plugin file or an initialization include:
add_shortcode( 'static_block_content', 'static_block_content' ); // (inferred) - Entry Point: When a post containing the shortcode is rendered, WordPress calls the callback:
static_block_content( $atts ) - Processing:
- The function extracts the
idfrom$atts. - It calls
$post = get_post( $atts['id'] );(Sink). - The function fails to verify
$post->post_statusor checkcurrent_user_can( 'read_post', $post->ID ).
- The function extracts the
- 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:
- Navigate: Use
browser_navigatetohttps://TARGET/wp-admin/post-new.php. - Extract Nonce: Use
browser_evalto get the REST nonce:window.wpApiSettings.nonce - Submit: Use
http_request(POST) to/wp-json/wp/v2/postswith theX-WP-Nonceheader.
- Navigate: Use
5. Exploitation Strategy
- 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. - Login: Authenticate as a Contributor user.
- Create Attacker Post: Create a new post containing the malicious shortcode.
- Trigger Execution: Request the permalink of the newly created post (or its preview URL).
- Exfiltrate: Parse the HTML response to find the content of post
123rendered 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:
- 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).
- Create a Private post as an Admin:
- Attacker Account:
- Create a user with the Contributor role:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123
- Create a user with the Contributor role:
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:
- Automated Check:
# Assuming the response was saved to response.html grep "FLAG_SENSITIVE_DATA_EXPOSED" response.html - Manual Confirmation: Log in as the Admin and verify that post
5is indeed marked asprivate, 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 apost_type, try targetingpage,attachment, or custom post types (likewp_blockorstatic_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.
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
@@ -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.