CVE-2026-2371

Greenshift <= 12.8.3 - Missing Authorization to Unauthenticated Private Reusable Block Disclosure via 'gspb_el_reusable_load'

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
12.8.4
Patched in
1d
Time to patch

Description

The Greenshift – animation and page builder blocks plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 12.8.3. This is due to missing authorization and post status validation in the `gspb_el_reusable_load()` AJAX handler. The handler accepts an arbitrary `post_id` parameter and renders the content of any `wp_block` post without checking `current_user_can('read_post', $post_id)` or verifying the post status. Combined with the nonce being exposed to unauthenticated users on any public page using the `[wp_reusable_render]` shortcode with `ajax="1"`, this makes it possible for unauthenticated attackers to retrieve the rendered HTML content of private, draft, or password-protected reusable blocks.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=12.8.3
PublishedMarch 6, 2026
Last updatedMarch 6, 2026

What Changed in the Fix

Changes introduced in v12.8.4

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2371 ## 1. Vulnerability Summary The **Greenshift – animation and page builder blocks** plugin (<= 12.8.3) contains an Insecure Direct Object Reference (IDOR) vulnerability in its AJAX handling logic. Specifically, the function `gspb_el_reusable_load()` (likel…

Show full research plan

Exploitation Research Plan: CVE-2026-2371

1. Vulnerability Summary

The Greenshift – animation and page builder blocks plugin (<= 12.8.3) contains an Insecure Direct Object Reference (IDOR) vulnerability in its AJAX handling logic. Specifically, the function gspb_el_reusable_load() (likely located in a file handling reusable block logic, such as blockrender/element/block.php or similar) fails to perform any capability checks or post-status validation before rendering the content of a post ID provided by the user.

Because the plugin also registers an unauthenticated AJAX handler (wp_ajax_nopriv_gspb_el_reusable_load) and exposes the necessary security nonce on pages utilizing the [wp_reusable_render] shortcode, unauthenticated attackers can retrieve the full rendered HTML of any reusable block (wp_block post type), including those marked as Private, Draft, or Password Protected.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: gspb_el_reusable_load
  • Vulnerable Parameter: post_id (The ID of the wp_block to be disclosed)
  • Nonce Parameter: nonce (or security - must be extracted from the frontend)
  • Authentication Level: Unauthenticated
  • Preconditions:
    • A reusable block exists (even if private).
    • The attacker must be able to obtain a valid nonce, which is provided by the plugin on any page using the [wp_reusable_render] shortcode with ajax="1".

3. Code Flow

  1. Entry Point: The plugin registers AJAX handlers:
    add_action('wp_ajax_gspb_el_reusable_load', 'gspb_el_reusable_load');
    add_action('wp_ajax_nopriv_gspb_el_reusable_load', 'gspb_el_reusable_load');
    
  2. Handler Execution: When admin-ajax.php receives the gspb_el_reusable_load action, it calls the handler.
  3. Missing Authorization: Inside gspb_el_reusable_load():
    • It retrieves $post_id = $_POST['post_id'].
    • It performs a nonce check (e.g., check_ajax_referer('gspb_el_nonce', 'nonce')).
    • Vulnerability: It calls get_post($post_id) and immediately proceeds to render the content (e.g., using do_blocks() or returning the post_content) without checking if the current user has the read_post capability for that ID or if the post status is publish.
  4. Information Disclosure: The rendered HTML of the private block is returned in the AJAX response.

4. Nonce Acquisition Strategy

The vulnerability description confirms that the nonce is exposed via the [wp_reusable_render] shortcode.

  1. Identify Script Localization: The plugin likely uses wp_localize_script to pass the nonce to the frontend for blocks using AJAX loading.
  2. Setup: Create a public page containing the shortcode to trigger the nonce exposure.
    • Shortcode: [wp_reusable_render ajax="1"]
  3. Extraction:
    • Use browser_navigate to view the page.
    • Use browser_eval to find the localized data. Based on Greenshift naming conventions, look for objects starting with gspb.
    • Target Variable (Inferred): window.gspb_vars?.nonce or window.greenshift_vars?.reusable_nonce.
    • Self-Correction: If the specific variable isn't found, search the HTML source for "nonce" within <script> tags associated with Greenshift assets.

5. Exploitation Strategy

Step 1: Data Discovery

First, identify the ID of a "Private" reusable block. In a real-world scenario, an attacker might iterate through IDs. For testing, we will create one.

Step 2: Nonce Retrieval

  1. Navigate to the page created in the Test Data Setup (containing the shortcode).
  2. Execute JS to grab the nonce:
    // Probable location of the nonce
    console.log(gspb_vars.nonce); 
    

Step 3: Unauthorized Content Retrieval

Send a POST request to the AJAX endpoint.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application-x-www-form-urlencoded
  • Body:
    action=gspb_el_reusable_load&post_id=[PRIVATE_BLOCK_ID]&nonce=[EXTRACTED_NONCE]
    

Step 4: Verification

The response should contain the rendered HTML content of the private block.

6. Test Data Setup

Perform the following via wp-cli:

  1. Create a Secret Reusable Block:

    wp post create --post_type=wp_block --post_title="Secret Credentials" --post_content="The administrative password is: Summer2024!" --post_status=private
    

    Note the returned ID (e.g., 123).

  2. Create a Public Nonce-Leaking Page:

    wp post create --post_type=page --post_title="Greenshift Test" --post_status=publish --post_content='[wp_reusable_render ajax="1"]'
    

7. Expected Results

  • Request: Unauthenticated POST to admin-ajax.php with the ID of the private block and the leaked nonce.
  • Response Code: 200 OK.
  • Response Body: Should contain the string "The administrative password is: Summer2024!" inside the rendered HTML output.

8. Verification Steps

  1. Confirm Post Status: Use wp post get [ID] --field=post_status to verify the block is indeed private.
  2. Confirm Accessibility: Verify that a standard request to /?p=[ID] as an unauthenticated user results in a 404 or a "Post not found" message.
  3. Compare Result: Confirm the content returned by the AJAX exploit matches the post_content of the private block.

9. Alternative Approaches

If the gspb_el_reusable_load action name is slightly different, use grep on the plugin directory to find wp_ajax_nopriv registrations:

grep -r "wp_ajax_nopriv_" /var/www/html/wp-content/plugins/greenshift-animation-and-page-builder-blocks/

If the nonce is not in gspb_vars, check for other localized objects like greenshift_data or gspb_config.

Check if your site is affected.

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