Critical Security Vulnerability: Money Creation Exploit in Wallet Transfer

Tagged: 

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #8750
    rjrefat
    Participant

    Dear Developer Team,

    I am writing to report a Critical Severity vulnerability in the do_wallet_transfer function of the Woo Wallet / TeraWallet plugin.

    This flaw allows malicious users to create money out of thin air by exploiting a “Credit-First” logic flaw combined with a Race Condition. I have confirmed this exploit on my production site where a user successfully transferred funds they did not have, inflating the total money supply in the system.

    1. The Logic Flaw (Root Cause)
    File: includes/class-woo-wallet-frontend.php Function: do_wallet_transfer()

    The vulnerability exists because the code credits the receiver before it successfully debits the sender.

    Current Vulnerable Logic:

    CREDIT the Receiver (woo_wallet()->wallet->credit).

    IF Credit is successful -> DEBIT the Sender.

    The Risk: If the Debit fails (e.g., due to low balance, database error, or a race condition lock), the system does not rollback the Credit. The receiver keeps the money, but the sender is never charged.

    2. Forensic Evidence (Database Logs)
    Here is a captured log from my database showing the attack in progress. A user sent 5 concurrent requests.

    Observed Behavior:

    Transaction #35 (Debit): The sender was correctly charged once ($0.20).

    Transaction #34, 36, 37, 38, 39 (Credit): The receiver was credited 5 times ($0.20 x 5 = $1.00).

    The Log Data:

    Plaintext

    ID | User | Type | Amount | Balance | Details
    —|——|——–|——–|———|——————————————
    34 | 297 | credit | 0.20 | 0.20 | Gift from User 295 (Exploit Success #1)
    35 | 295 | debit | 0.20 | 0.19 | Wallet funds transfer (Legit Deduct)
    36 | 297 | credit | 0.20 | 0.40 | Gift from User 295 (Exploit Success #2)
    37 | 297 | credit | 0.20 | 0.60 | Gift from User 295 (Exploit Success #3)
    38 | 297 | credit | 0.20 | 0.80 | Gift from User 295 (Exploit Success #4)
    39 | 297 | credit | 0.20 | 1.00 | Gift from User 295 (Exploit Success #5)
    Result: The sender spent $0.20, but the receiver got $1.00. The system lost $0.80.

    3. The Exploit Scenario (How they did it)
    Setup: The attacker uses a script (e.g., Python) to send 5 simultaneous HTTP POST requests to the “Wallet Transfer” endpoint.

    Execution: All 5 requests hit the server at the exact same millisecond.

    The Race:

    All 5 requests execute woo_wallet()->wallet->credit(…) successfully because there are no checks preventing incoming money.

    The system then tries to execute woo_wallet()->wallet->debit(…).

    The Failure:

    Only 1 request succeeds in debiting the user (locking the row).

    The other 4 requests fail the debit (because the balance is now too low or the database is locked).

    Crucial Error: The code does not check if the debit failed. It has already credited the receiver, so the money is permanently duplicated.

    4. Required Fix (Debit First Pattern)
    The logic must be reversed. You must successfully debit the sender before you credit the receiver.

    Corrected Logic Flow:

    DEBIT Sender.

    IF Debit is Successful -> CREDIT Receiver.

    ELSE (Debit Failed) -> Stop and Show Error.

    Patch Suggestion (includes/class-woo-wallet-frontend.php):

    PHP

    // … Inside do_wallet_transfer() …

    // 1. Perform Debit FIRST
    $debit_transaction_id = woo_wallet()->wallet->debit( get_current_user_id(), $debit_amount, $debit_note );

    if ( $debit_transaction_id ) {
    // 2. Debit Succeeded, NOW Credit the Receiver
    $credit_transaction_id = woo_wallet()->wallet->credit( $whom->ID, $credit_amount, $credit_note );

    if ( $credit_transaction_id ) {
    // Success: Log fees and hooks
    update_wallet_transaction_meta( $debit_transaction_id, ‘_wallet_transfer_charge’, $transfer_charge, get_current_user_id() );
    do_action( ‘woo_wallet_transfer_amount_debited’, $debit_transaction_id, get_current_user_id(), $whom->ID );
    do_action( ‘woo_wallet_transfer_amount_credited’, $credit_transaction_id, $whom->ID, get_current_user_id() );

    $response = array(
    ‘is_valid’ => true,
    ‘message’ => __( ‘Amount transferred successfully!’, ‘woo-wallet’ ),
    );
    } else {
    // Edge Case: Debit worked, but Credit failed. REFUND the sender immediately.
    woo_wallet()->wallet->credit( get_current_user_id(), $debit_amount, ‘Refund for failed transfer’ );
    $response = array( ‘is_valid’ => false, ‘message’ => __( ‘Transfer failed. Please try again.’, ‘woo-wallet’ ) );
    }
    } else {
    // Debit Failed (Insufficient funds or Race Condition). Do NOT credit receiver.
    $response = array(
    ‘is_valid’ => false,
    ‘message’ => __( ‘Transfer failed. Insufficient funds.’, ‘woo-wallet’ ),
    );
    }
    Please prioritize this fix in the next update, as this vulnerability directly impacts financial data integrity.

    Regards, Refat

Viewing 1 post (of 1 total)
  • You must be logged in to reply to this topic.

Login

Register

A link to set a new password will be sent to your email address.

Your personal data will be used to support your experience throughout this website, to manage access to your account, and for other purposes described in our privacy policy.

WhatsApp