CVE-2026-39488

SureCart <= 4.0.2 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
4.0.3
Patched in
21d
Time to patch

Description

The SureCart plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.0.2. This makes it possible for authenticated attackers, with contributor-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.0.2
PublishedMarch 26, 2026
Last updatedApril 15, 2026
Affected pluginsurecart

What Changed in the Fix

Changes introduced in v4.0.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: SureCart <= 4.0.2 - Missing Authorization ## 1. Vulnerability Summary The SureCart plugin for WordPress (versions up to and including 4.0.2) is vulnerable to unauthorized access due to missing or insufficient capability checks on several REST API endpoints. Specificall…

Show full research plan

Exploitation Research Plan: SureCart <= 4.0.2 - Missing Authorization

1. Vulnerability Summary

The SureCart plugin for WordPress (versions up to and including 4.0.2) is vulnerable to unauthorized access due to missing or insufficient capability checks on several REST API endpoints. Specifically, the BrandController lacks proper permission_callback restrictions (or uses a low-privilege check like is_user_logged_in), allowing authenticated users with Contributor-level permissions to modify store identity settings, such as the brand name, address, and logo.

2. Attack Vector Analysis

  • Endpoint: /wp-json/surecart/v1/brand
  • HTTP Method: POST (triggers edit) or DELETE (triggers purgeLogo)
  • Vulnerable Controller: SureCart\Controllers\Rest\BrandController
  • Vulnerable Functions: edit(\WP_REST_Request $request) and purgeLogo(\WP_REST_Request $request)
  • Authentication: Required (Contributor level)
  • Nonce: Required (wp_rest action nonce)
  • Precondition: The plugin must be installed and initialized.

3. Code Flow

  1. REST Registration (Inferred): The plugin registers REST routes in a service provider. The BrandController methods are mapped to the /surecart/v1/brand endpoint.
  2. Request Entry: A Contributor user sends a POST request to /wp-json/surecart/v1/brand.
  3. Authorization Check: The permission_callback for this route fails to check for manage_options (Administrator) and instead allows any logged-in user or those with read / edit_posts (Contributor) capabilities.
  4. Execution (edit): The BrandController::edit function is called.
  5. Data Sink: edit calls Brand::with( [ 'address' ] )->update( $request->get_json_params() ).
  6. Persistence: The Brand model updates the store information, affecting how the ecommerce store appears to all customers.

4. Nonce Acquisition Strategy

The SureCart REST API uses the standard WordPress REST authentication, which requires an X-WP-Nonce header for authenticated requests. Since the attacker has Contributor access, they can obtain this nonce from the WordPress admin dashboard.

  1. Login: Authenticate as a Contributor user.
  2. Navigate: Use browser_navigate to http://localhost:8080/wp-admin/.
  3. Extract: Use browser_eval to extract the REST nonce from the global wpApiSettings object.
    • JavaScript: window.wpApiSettings.nonce
  4. Action: This nonce is valid for the wp_rest action and can be used in the X-WP-Nonce header for the exploit request.

5. Exploitation Strategy

Step 1: Update Brand Information (Unauthorized Action)

Modify the store's brand name and address, which should be restricted to administrators.

  • URL: http://localhost:8080/wp-json/surecart/v1/brand
  • Method: POST
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Body:
{
    "name": "Exploited Store Name",
    "address": {
        "line_1": "1337 Hacker Way",
        "city": "CyberCity",
        "country": "US"
    }
}

Step 2: Purge Store Logo (Unauthorized Action)

Delete the store's logo image.

  • URL: http://localhost:8080/wp-json/surecart/v1/brand/logo (Inferred path for purgeLogo)
  • Method: DELETE
  • Headers:
    • X-WP-Nonce: [EXTRACTED_NONCE]

6. Test Data Setup

  1. Plugin Installation: Ensure SureCart is active.
  2. User Creation: Create a user with the contributor role.
wp user create attacker attacker@example.com --role=contributor --user_pass=password
  1. Initial State: Observe the current Brand Name (usually the site name or "SureCart Store").

7. Expected Results

  • The REST API should return a 200 OK or 201 Created response.
  • The response body should contain the updated brand object reflecting the "Exploited Store Name".
  • A request to GET /wp-json/surecart/v1/brand (even as a non-logged-in user) should show the modified brand data.

8. Verification Steps

  1. Check via WP-CLI: Verify if the brand data in the database or cached options has changed.
# SureCart often stores account/brand data in transients or options
wp transient get surecart_account
wp option get sc_previous_account
  1. Observe Frontend: Visit the SureCart shop or checkout page (if configured) to see the "Exploited Store Name" in the header/footer.

9. Alternative Approaches

If the BrandController is not the target, check for the "Seed" functionality in AccountService.php. Seeding a store with dummy products and data is a high-impact "unauthorized action."

  • Alternative Target: /wp-json/surecart/v1/account/seed
  • Payload: {"products": [{"name": "Malicious Product", "price": 0}]}
  • Significance: If a Contributor can seed the store, they can flood the database with arbitrary products and potentially manipulate pricing.
Research Findings
Static analysis — not yet PoC-verified

Summary

The SureCart plugin for WordPress is vulnerable to unauthorized data modification due to missing capability checks on REST API endpoints handled by the BrandController. Authenticated attackers with Contributor-level access or higher can exploit this to change store branding information, such as the business name and address, or delete the store logo.

Vulnerable Code

// app/src/Controllers/Rest/BrandController.php line 27
public function edit( \WP_REST_Request $request ) {
	return Brand::with( [ 'address' ] )->update( $request->get_json_params() );
}

---

// app/src/Controllers/Rest/BrandController.php line 38
public function purgeLogo( \WP_REST_Request $request ) {
	return Brand::with( [ 'address' ] )->where( $request->get_query_params() )->purgeLogo();
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/surecart/4.0.2/app/src/Controllers/Rest/BrandController.php /home/deploy/wp-safety.org/data/plugin-versions/surecart/4.0.3/app/src/Controllers/Rest/BrandController.php
--- /home/deploy/wp-safety.org/data/plugin-versions/surecart/4.0.2/app/src/Controllers/Rest/BrandController.php	2023-08-31 20:37:32.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/surecart/4.0.3/app/src/Controllers/Rest/BrandController.php	2026-03-12 19:24:02.000000000 +0000
@@ -16,7 +16,7 @@
 	 * @return \WP_REST_Response|\WP_Error
 	 */
 	public function find( \WP_REST_Request $request ) {
-		return Brand::with( [ 'address' ] )->find();
+		return Brand::with( [ 'address', 'logo', 'dark_logo' ] )->find();
 	}
 
 	/**
@@ -27,7 +27,7 @@
 	 * @return \WP_REST_Response|\WP_Error
 	 */
 	public function edit( \WP_REST_Request $request ) {
-		return Brand::with( [ 'address' ] )->update( $request->get_json_params() );
+		return Brand::with( [ 'address', 'logo', 'dark_logo' ] )->update( $request->get_json_params() );
 	}
 
 	/**
@@ -38,6 +38,6 @@
 	 * @return \WP_REST_Response
 	 */
 	public function purgeLogo( \WP_REST_Request $request ) {
-		return Brand::with( [ 'address' ] )->where( $request->get_query_params() )->purgeLogo();
+		return Brand::with( [ 'address', 'logo', 'dark_logo' ] )->where( $request->get_query_params() )->purgeLogo();
 	}
 }

Exploit Outline

The exploit target is the SureCart REST API, specifically endpoints managed by the BrandController. 1. Authentication: The attacker must be authenticated to the WordPress site with at least Contributor-level privileges. 2. Nonce Acquisition: The attacker retrieves a valid REST API nonce (X-WP-Nonce) from the WordPress dashboard, usually found in the `wpApiSettings.nonce` JavaScript variable. 3. Brand Modification: The attacker sends a POST request to `/wp-json/surecart/v1/brand`. The payload includes a JSON object with keys like 'name' or 'address' to overwrite existing store settings. Because the endpoint lacks a restrictive permission_callback (e.g., one checking for `manage_options`), the request is authorized. 4. Logo Deletion: The attacker can also send a DELETE request to `/wp-json/surecart/v1/brand/logo` to remove the existing store logo without authorization.

Check if your site is affected.

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