From 1d3ea597f4efdf049d10120e5ca25ffd613ae949 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Wed, 17 Jun 2026 06:53:00 +0300 Subject: [PATCH] fix(security): wallet balance check with FOR UPDATE, remove user-supplied ID in signup, hardcoded IP to env --- backend/auth/signup.php | 6 +- backend/functions.php | 3 +- .../ride/payment/process_ride_payments.php | 55 ++++++++++++++----- 3 files changed, 43 insertions(+), 21 deletions(-) diff --git a/backend/auth/signup.php b/backend/auth/signup.php index f4bffdc..31c143b 100644 --- a/backend/auth/signup.php +++ b/backend/auth/signup.php @@ -11,7 +11,6 @@ $password = filterRequest("password"); $gender = filterRequest("gender"); $birthdate = filterRequest("birthdate"); $site = filterRequest("site"); -$id = filterRequest("id"); // تشفير البيانات الحساسة $phone = $encryptionHelper->encryptData($phone); @@ -39,14 +38,13 @@ try { exit; } - // إدخال البيانات الجديدة + // إدخال البيانات الجديدة (مع ID تلقائي) $sql = "INSERT INTO passengers ( id, phone, email, password, gender, birthdate, site, first_name, last_name ) VALUES ( - :id, :phone, :email, :password, :gender, :birthdate, :site, :first_name, :last_name + UUID_SHORT(), :phone, :email, :password, :gender, :birthdate, :site, :first_name, :last_name )"; $stmt = $con->prepare($sql); - $stmt->bindParam(":id", $id); $stmt->bindParam(":phone", $phone); $stmt->bindParam(":email", $email); $stmt->bindParam(":password", $hashedPassword); diff --git a/backend/functions.php b/backend/functions.php index 0a4ea3c..7c10a2c 100644 --- a/backend/functions.php +++ b/backend/functions.php @@ -44,8 +44,7 @@ function isAllowedSocketUrl(string $url): bool { } function sendToLocationServer($action, $data) { - // رابط سيرفر اللوكيشن الداخلي أو العام - $url = "http://188.68.36.205:2021"; + $url = getenv('LOCATION_SERVER_URL') ?: 'http://188.68.36.205:2021'; if (!isAllowedSocketUrl($url)) { error_log("[SSRF_BLOCKED] Attempted connection to: $url"); return; diff --git a/walletintaleq.intaleq.xyz/v2/main/ride/payment/process_ride_payments.php b/walletintaleq.intaleq.xyz/v2/main/ride/payment/process_ride_payments.php index 5b9b427..113809e 100755 --- a/walletintaleq.intaleq.xyz/v2/main/ride/payment/process_ride_payments.php +++ b/walletintaleq.intaleq.xyz/v2/main/ride/payment/process_ride_payments.php @@ -41,13 +41,12 @@ $passengerId = filterRequest("passengerId"); $paymentAmount = filterRequest("paymentAmount"); $paymentMethod = filterRequest("paymentMethod"); $walletChecked = filterRequest("walletChecked"); // 'true' or 'false' -$passengerWalletBurc = filterRequest("passengerWalletBurc"); // passenger balance before operation $authToken = filterRequest("authToken"); // kept for logging/audit, not used for auth // --- Validate required fields --- if (empty($rideId) || empty($driverId) || empty($passengerId) || !isset($paymentAmount) || empty($paymentMethod) || - !isset($walletChecked) || !isset($passengerWalletBurc)) { + !isset($walletChecked)) { printFailure("Missing required parameters for payment processing."); exit; } @@ -79,33 +78,59 @@ try { // 3b. Deduct from passenger wallet (if wallet payment) if ($walletChecked === 'true') { + // Check actual balance with row lock + $stmtBalance = $con->prepare( + "SELECT COALESCE(SUM(balance), 0) AS current_balance + FROM passengerWallet + WHERE passenger_id = :passenger_id + FOR UPDATE" + ); + $stmtBalance->execute([':passenger_id' => $passengerId]); + $balanceRow = $stmtBalance->fetch(PDO::FETCH_ASSOC); + $currentBalance = floatval($balanceRow['current_balance']); + + $deductionAmount = floatval($paymentAmount); + if ($currentBalance < $deductionAmount) { + throw new Exception("Insufficient wallet balance. Required: $deductionAmount, Available: $currentBalance"); + } + $stmtPassengerWallet = $con->prepare( "INSERT INTO `passengerWallet` (`passenger_id`, `balance`) VALUES (:passenger_id, :balance)" ); $stmtPassengerWallet->execute([ ':passenger_id' => $passengerId, - ':balance' => (-1) * floatval($paymentAmount), + ':balance' => (-1) * $deductionAmount, ]); if ($stmtPassengerWallet->rowCount() <= 0) { throw new Exception("Failed to deduct from passenger wallet."); } - } - // 3c. Settle existing passenger debt (if balance was negative) - if (floatval($passengerWalletBurc) < 0) { - $stmtPassengerDebt = $con->prepare( - "INSERT INTO `passengerWallet` (`passenger_id`, `balance`) - VALUES (:passenger_id, :balance)" + // 3c. Settle existing debt (use actual balance after deduction) + $stmtBalanceAfter = $con->prepare( + "SELECT COALESCE(SUM(balance), 0) AS balance_after + FROM passengerWallet + WHERE passenger_id = :passenger_id + FOR UPDATE" ); - $stmtPassengerDebt->execute([ - ':passenger_id' => $passengerId, - ':balance' => (-1) * floatval($passengerWalletBurc), - ]); + $stmtBalanceAfter->execute([':passenger_id' => $passengerId]); + $balanceAfterRow = $stmtBalanceAfter->fetch(PDO::FETCH_ASSOC); + $balanceAfter = floatval($balanceAfterRow['balance_after']); - if ($stmtPassengerDebt->rowCount() <= 0) { - throw new Exception("Failed to settle passenger debt."); + if ($balanceAfter < 0) { + $stmtPassengerDebt = $con->prepare( + "INSERT INTO `passengerWallet` (`passenger_id`, `balance`) + VALUES (:passenger_id, :balance)" + ); + $stmtPassengerDebt->execute([ + ':passenger_id' => $passengerId, + ':balance' => (-1) * $balanceAfter, + ]); + + if ($stmtPassengerDebt->rowCount() <= 0) { + throw new Exception("Failed to settle passenger debt."); + } } }