Content Blocks (Custom Post Widget) <= 3.3.9 - Authenticated (Author+) Stored Cross-Site Scripting via content_block Shortcode
Description
The Content Blocks (Custom Post Widget) plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's content_block shortcode in all versions up to, and including, 3.3.9 due to insufficient input sanitization and output escaping on user supplied values consumed from user-created content blocks. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=3.3.9What Changed in the Fix
Changes introduced in v3.4.1
Source Code
WordPress.org SVNlook at `custom-post-widget.php` line 154 again. * `$content = apply_filters( 'the_content', $post->post_content );` * This is the code for `cpw_content_block` shortcode. * If the vulnerability is in the *other* shortcode `content_block` (defined in `shortcode.php`), and that one …
Show full research plan
look at custom-post-widget.php line 154 again.
* $content = apply_filters( 'the_content', $post->post_content );
* This is the code for cpw_content_block shortcode.
* If the vulnerability is in the other shortcode content_block (defined in shortcode.php), and that one doesn't use apply_filters.
* Let's assume the `title_tag` injection is the primary vector because it allows an Author to use a perfectly safe Post Title as the body of an injected `<script>` tag.
1. Vulnerability Summary.
2. Attack Vector Analysis (Author+).
3. Code Flow (Inferred `shortcode.php`).
4. Nonce Strategy (None for shortcode usage).
5. Exploitation Strategy (Step-by-step).
6. Test Data Setup.
7. Expected Results.
8. Verification.
I will use `title_tag` as the primary exploit candidate and `class` as the alternative.
One more check: "insufficient input sanitization and output escaping on user supplied values **consumed from user-created content blocks**."
This wording is very specific.
If the Author creates a block and fills in the `_content_block_information` field.
If the short
Summary
The Content Blocks plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the `content_block` shortcode. An authenticated attacker can manipulate the `markup` attribute to inject unauthorized HTML tags such as `<script>`, which causes the content of a linked content block to be executed as JavaScript in the victim's browser.
Vulnerable Code
// shortcode.php line 31 $markup = sanitize_text_field ( $params['markup'] ); --- // shortcode.php line 69 $content = '<' . $markup . ' class="' . $class . '" id="custom_post_widget-' . $id . '">'; if ( $show_post_title == 'yes' ) { $content .= '<' . $title_tag . ' class="custom_post_widget_title">' . $post -> post_title . '</' . $title_tag . '>'; } $content .= apply_filters( 'the_content', $post -> post_content ); // ... $content .= '</' . $markup . '>';
Security Fix
@@ -1,5 +1,7 @@ <?php +if ( ! defined( 'ABSPATH' ) ) exit; + // Add the ability to display the content block in a reqular post using a shortcode function custom_post_widget_shortcode ( $atts ) { $params = shortcode_atts ( array ( @@ -28,7 +30,11 @@ if ( ! in_array( $title_tag, $allowed_tags ) ) { $title_tag = 'h3'; // Default to 'h3' if the specified tag is not allowed } - $markup = sanitize_text_field ( $params['markup'] ); + $markup = strtolower( sanitize_text_field( $params['markup'] ) ); + $allowed_markup_tags = array( 'div', 'section', 'article', 'aside', 'header', 'footer', 'main', 'span', 'p' ); + if ( ! in_array( $markup, $allowed_markup_tags, true ) ) { + $markup = 'div'; + } $template = sanitize_text_field ( $params['template'] ); if ( $slug ) {
Exploit Outline
1. Login as an authenticated user with Contributor-level access or higher. 2. Create a new 'Content Block' post (post_type: `content_block`). Set the content of this block to the JavaScript payload (e.g., `alert(origin)`). Note the post ID of this block. 3. Create or edit a standard post or page. 4. Insert the shortcode `[content_block id=YOUR_BLOCK_ID markup="script"]` into the editor. 5. Publish or preview the post. 6. The plugin's shortcode handler will output the block content wrapped in `<script>` tags instead of the intended `<div>` tags, causing the browser to execute the content as JavaScript.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.