CVE-2026-27346

B2BKing — Ultimate WooCommerce B2B and Wholesale Plugin — Wholesale Prices, Bulk Order Form & More < 5.2.10 - Missing Authorization

lowMissing Authorization
2.7
CVSS Score
2.7
CVSS Score
low
Severity
5.2.10
Patched in
2d
Time to patch

Description

The B2BKing — Ultimate WooCommerce B2B and Wholesale Plugin — Wholesale Prices, Bulk Order Form & More plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to 5.2.10. This makes it possible for authenticated attackers, with shop manager-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<5.2.10
PublishedMay 25, 2026
Last updatedMay 26, 2026

What Changed in the Fix

Changes introduced in v5.2.10

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-27346 ## 1. Vulnerability Summary The **B2BKing — Ultimate WooCommerce B2B and Wholesale Plugin** (versions < 5.2.10) is vulnerable to **Missing Authorization**. Specifically, several AJAX functions registered in the `B2bkingcore_Admin` class (located in `adm…

Show full research plan

Exploitation Research Plan - CVE-2026-27346

1. Vulnerability Summary

The B2BKing — Ultimate WooCommerce B2B and Wholesale Plugin (versions < 5.2.10) is vulnerable to Missing Authorization. Specifically, several AJAX functions registered in the B2bkingcore_Admin class (located in admin/class-b2bking-admin.php) fail to perform capability checks (e.g., current_user_can('manage_options')). This allow authenticated users with roles such as Shop Manager to perform administrative actions, such as bulk-moving users into different B2B customer groups, which can lead to unauthorized price access or permission escalation within the B2B system.

2. Attack Vector Analysis

  • Vulnerable Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: b2bking_set_users_in_group (derived from the tool's container ID in adminstyle.css) or b2bking_set_users_in_bulk.
  • HTTP Method: POST
  • Authentication: Authenticated, Shop Manager role (or any role that can access the WordPress admin but lacks B2BKing management privileges).
  • Parameters:
    • action: b2bking_set_users_in_group
    • security: A valid WordPress nonce for the action b2bking_admin_nonce.
    • users: A single user ID or an array/comma-separated list of user IDs to modify.
    • group: The ID of the b2bking_group post type to assign users to.

3. Code Flow

  1. Registration: In admin/class-b2bking-admin.php, the plugin registers AJAX handlers during initialization (likely inside the plugins_loaded or init hook, or within the B2bkingcore_Admin constructor).
  2. Hook: add_action('wp_ajax_b2bking_set_users_in_group', array($this, 'b2bking_set_users_in_group')).
  3. Execution: When a Shop Manager sends a POST request to admin-ajax.php with the specified action:
    • The function b2bking_set_users_in_group() is called.
    • It calls check_ajax_referer('b2bking_admin_nonce', 'security') to verify the nonce.
    • Vulnerability: It fails to call current_user_can('manage_options').
    • It proceeds to iterate through the users parameter and updates their user meta (typically b2bking_customer_group) to match the group parameter.

4. Nonce Acquisition Strategy

The B2BKing plugin localizes its admin data into a global JavaScript object named b2bking. The nonce is typically assigned to b2bking.security.

Strategy:

  1. Identification: The admin/class-b2bking-admin.php registers panels for the Product Edit page (woocommerce_product_data_panels). Shop Managers have permission to edit products.
  2. Setup: The PoC agent should navigate to an existing product's edit page.
  3. Extraction:
    • Navigate to /wp-admin/post.php?post=[PRODUCT_ID]&action=edit.
    • Use browser_eval to extract the nonce:
      window.b2bking?.security || window.b2bking?.nonce
      
    • Note: If the Shop Manager cannot access the B2BKing Tools page directly, they can still obtain this nonce because the plugin enqueues its global admin scripts on all product pages to handle the "B2BKing" tab/panel.

5. Exploitation Strategy

Step-by-Step Plan:

  1. Login: Authenticate as a Shop Manager.
  2. Nonce Extraction: Navigate to the product editor and extract b2bking.security.
  3. Target Identification: Identify a b2bking_group ID (can be listed via wp post list --post_type=b2bking_group) and a target User ID (e.g., the Shop Manager's own ID to gain discounts).
  4. Execution: Send a POST request to admin-ajax.php.

Request Details:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body:
    action=b2bking_set_users_in_group&security=[NONCE]&users=[USER_ID]&group=[GROUP_ID]
    

6. Test Data Setup

  1. Create Group: wp post create --post_type=b2bking_group --post_title="VIP Wholesale" --post_status=publish
    • Note the ID of this group.
  2. Create Shop Manager: wp user create shopmanager shopmanager@example.com --role=shop_manager --user_pass=password
  3. Create Target User: wp user create victim victim@example.com --role=subscriber
    • Note the ID of this user.
  4. Verify Plugin State: Ensure B2BKing is active and a product exists for the Shop Manager to visit.

7. Expected Results

  • Success Response: The server returns a success message (often 1, or a JSON object like {"success": true}).
  • Effect: The user meta for the target user is updated.

8. Verification Steps

After the HTTP request, use WP-CLI to verify the metadata change:

# Check if the victim user is now assigned to the group
wp user meta get [VICTIM_USER_ID] b2bking_customer_group

The output should match the GROUP_ID used in the exploit.

9. Alternative Approaches

If b2bking_set_users_in_group is not the exact action name:

  • Examine CSS: Check admin/assets/css/adminstyle.css for other tool IDs (e.g., b2bking_set_category_in_bulk).
  • Scan AJAX Actions: Look for any wp_ajax_ registration in admin/class-b2bking-admin.php that involves "save", "update", or "set".
  • Check for Export Vulnerability: Try action=b2bking_download_products (referenced by ID b2bking_download_products_button in CSS) to see if a Shop Manager can trigger a CSV export of wholesale data they shouldn't see.
Research Findings
Static analysis — not yet PoC-verified

Summary

The B2BKing plugin for WordPress is vulnerable to a missing authorization check on its administrative AJAX functions. This allows authenticated attackers with Shop Manager privileges to perform unauthorized actions, such as bulk-moving users into B2B customer groups, which can lead to unauthorized access to wholesale pricing or permissions.

Vulnerable Code

// admin/class-b2bking-admin.php

// The plugin registers several AJAX actions intended for administrative use
// but fails to verify if the requesting user has the 'manage_options' or 'manage_woocommerce' capability.

add_action('wp_ajax_b2bking_set_users_in_group', array($this, 'b2bking_set_users_in_group'));

---

// In admin/class-b2bking-admin.php (inferred location based on admin tool registration)
public function b2bking_set_users_in_group() {
    // Verify the nonce provided in the request
    check_ajax_referer('b2bking_admin_nonce', 'security');

    // VULNERABILITY: No check for current_user_can('manage_options') or similar admin capability

    $users = isset($_POST['users']) ? sanitize_text_field($_POST['users']) : '';
    $group = isset($_POST['group']) ? sanitize_text_field($_POST['group']) : '';

    // Proceed to modify user metadata based on input
    if (!empty($users) && !empty($group)) {
        // ... logic to update b2bking_customer_group meta ...
    }
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.00/admin/assets/css/adminglobal.css /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.10/admin/assets/css/adminglobal.css
--- /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.00/admin/assets/css/adminglobal.css	2026-04-05 22:45:30.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.10/admin/assets/css/adminglobal.css	2026-05-10 17:23:52.000000000 +0000
@@ -4096,12 +4096,14 @@
     min-width: 65px;
 }
 .approval_badge.active{
-    background: rgba(40, 167, 69, 0.1) !important;
-    color: #28a745 !important;
+    background: #f4f6f5 !important;
+    border: 1px solid #e5e9e7 !important;
+    color: #5d7466 !important;
 }
 .approval_badge.pending{
-    background: rgba(255, 193, 7, 0.1) !important;
-    color: #ffc107 !important;
+    background: #fff8e5 !important;
+    border: 1px solid #f2dfad !important;
+    color: #9a6a00 !important;
     cursor: pointer;
     position: relative;
 }
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.00/admin/assets/css/adminstyle.css /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.10/admin/assets/css/adminstyle.css
--- /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.00/admin/assets/css/adminstyle.css	2026-05-10 17:27:52.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.10/admin/assets/css/adminstyle.css	2026-05-10 17:23:52.000000000 +0000
@@ -31,6 +31,9 @@
 #b2bking_admin_form .checkbox input{
 	margin:0;
 }
+.b2bking_settings_saved_swal_title {
+    font-size: 16px !important;
+}
 .b2bking_button_color_gold.b2bking_button_color_gold_main button{
   background: radial-gradient(141.77% 141.08% at 100.26% 99.25%, #cd4f72 0%, #e59a45 100%) !important;
 }
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.00/admin/assets/js/admin.js /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.10/admin/assets/js/admin.js
--- /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.00/admin/assets/js/admin.js	2026-04-05 22:45:30.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.10/admin/assets/js/admin.js	2026-05-10 17:23:52.000000000 +0000
@@ -45,13 +45,40 @@
 		    $(this).closest('.message').transition('fade');
 		});
 
+		var settingsSavedNoticeKey = 'b2bking_settings_saved_notice';
+
 		// On Submit (Save Settings), Get Current Tab and Pass The Tab as a Setting. 
 		$('#b2bking_admin_form').on('submit', function() {
 			let tabInput = document.querySelector('#b2bking_current_tab_setting_input');
 		    tabInput.value = document.querySelector('.item.active').dataset.tab;
+		    sessionStorage.setItem(settingsSavedNoticeKey, '1');
 		    return true; 
 		});
 
+		const urlParams = new URLSearchParams(window.location.search);
+		if ((urlParams.get('settings-updated') === 'true' || sessionStorage.getItem(settingsSavedNoticeKey) === '1') && typeof Swal !== 'undefined'){
+			sessionStorage.removeItem(settingsSavedNoticeKey);
+			const Toast = Swal.mixin({
+			  toast: true,
+			  position: 'bottom-end',
+			  showConfirmButton: false,
+			  timer: 1000,
+			  timerProgressBar: false,
+			  customClass: {
+			    title: 'b2bking_settings_saved_swal_title'
+			  },
+			  didOpen: (toast) => {
+			    toast.addEventListener('mouseenter', Swal.stopTimer)
+			    toast.addEventListener('mouseleave', Swal.resumeTimer)
+			  }
+			})
+
+			Toast.fire({
+			  icon: 'success',
+			  title: b2bking.settings_saved_successfully
+			});
+		}
+
 		
 
 	});
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.00/admin/class-b2bking-admin.php /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.10/admin/class-b2bking-admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.00/admin/class-b2bking-admin.php	2026-04-05 22:45:30.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/b2bking-wholesale-for-woocommerce/5.2.10/admin/class-b2bking-admin.php	2026-05-10 17:23:52.000000000 +0000
@@ -8132,6 +8132,7 @@
 			    'groupspage' => admin_url( 'admin.php?page=b2bking_groups'),
 			    'saving'	=> esc_html__('Saving...','b2bking'),
 			    'settings_saved' => esc_html__('Settings Saved','b2bking'),
+			    'settings_saved_successfully' => esc_html__('Settings saved successfully','b2bking'),
 			    'users_have_been_moved' => esc_html__('All users have been moved to your chosen group','b2bking'),
 			    'registration_form_shortcodes_text' => esc_html__('Registration Form Shortcodes','b2bking'),
 			    'bulkorder_form_shortcodes_text' => esc_html__('Order Form Shortcodes','b2bking'),

Exploit Outline

To exploit this vulnerability, an attacker must have at least Shop Manager level access. 1. Login to the WordPress dashboard as a Shop Manager. 2. Navigate to a standard administrative page where the plugin enqueues its scripts (such as a Product Edit page) and extract the 'b2bking_admin_nonce' from the global 'b2bking' JavaScript object. 3. Identify the target User ID and the ID of a B2B group (b2bking_group) the attacker wishes to assign the user to. 4. Send a POST request to `/wp-admin/admin-ajax.php` with the action `b2bking_set_users_in_group`. The payload should include the extracted nonce in the 'security' parameter, the target User ID(s) in 'users', and the target Group ID in 'group'. 5. Because the plugin lacks a capability check, the AJAX request will succeed, updating the user's customer group and granting them associated B2B privileges or discounts.

Check if your site is affected.

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