fix(security): fix pervasive IDOR - force JWT user identity in 9 endpoints, fix host injection, exception leaks, wallet auth
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
// استقبال المتغيرات
|
||||
$driverID = filterRequest("driverID");
|
||||
$passengerID = filterRequest("passengerID");
|
||||
// استقبال المتغيرات — force user IDs from JWT based on role
|
||||
$rideID = filterRequest("rideID");
|
||||
$note = filterRequest("note");
|
||||
|
||||
// Force driverID/passengerID from JWT based on user role
|
||||
if ($role === 'driver') {
|
||||
$driverID = $user_id;
|
||||
$passengerID = filterRequest("passengerID");
|
||||
} else {
|
||||
$passengerID = $user_id;
|
||||
$driverID = filterRequest("driverID");
|
||||
}
|
||||
|
||||
// تنفيذ الإدخال بطريقة آمنة
|
||||
$sql = "INSERT INTO `canecl` (`driverID`, `passengerID`, `rideID`, `note`)
|
||||
VALUES (:driverID, :passengerID, :rideID, :note)";
|
||||
|
||||
@@ -17,7 +17,12 @@ function generateUniqueCode($con) {
|
||||
}
|
||||
}
|
||||
|
||||
$driverId = filterRequest("driverId");
|
||||
// Force driverId from JWT — only drivers can manage invitations
|
||||
if ($role !== 'driver') {
|
||||
jsonError("Only drivers can create invitations");
|
||||
exit;
|
||||
}
|
||||
$driverId = $user_id;
|
||||
$inviterDriverPhone = filterRequest("inviterDriverPhone");
|
||||
|
||||
// 🔐 تشفير رقم الهاتف
|
||||
@@ -52,7 +57,8 @@ if ($checkStmt->rowCount() > 0) {
|
||||
"expirationTime" => $expirationTime
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[invitor/add] DB Error: " . $e->getMessage());
|
||||
jsonError("Database error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +89,8 @@ if ($checkStmt->rowCount() > 0) {
|
||||
jsonError("Failed to save invite data");
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[invitor/add] DB Error: " . $e->getMessage());
|
||||
jsonError("Database error occurred");
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -7,8 +7,17 @@ header('Content-Type: application/json');
|
||||
|
||||
try {
|
||||
$inviteId = filterRequest("invite_id");
|
||||
$driverId = filterRequest("driver_id");
|
||||
$passengerId = filterRequest("passenger_id");
|
||||
// Force user ID from JWT based on role
|
||||
if ($role === 'driver') {
|
||||
$driverId = $user_id;
|
||||
$passengerId = null;
|
||||
} elseif ($role === 'passenger') {
|
||||
$passengerId = $user_id;
|
||||
$driverId = null;
|
||||
} else {
|
||||
echo json_encode(["status" => "failure", "message" => "Invalid user role."]);
|
||||
exit;
|
||||
}
|
||||
$countryCode = filterRequest("country_code"); // Expected: Jordan, Syria, Egypt
|
||||
|
||||
if (empty($inviteId)) {
|
||||
@@ -88,6 +97,7 @@ try {
|
||||
}
|
||||
|
||||
function addWalletBalance($url, $userId, $userType, $amount) {
|
||||
$s2sKey = getenv('S2S_SHARED_KEY');
|
||||
$data = [
|
||||
"user_id" => $userId,
|
||||
"user_type" => $userType,
|
||||
@@ -100,6 +110,11 @@ function addWalletBalance($url, $userId, $userType, $amount) {
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
if ($s2sKey) {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-Auth-Token: $s2sKey"]);
|
||||
}
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $response;
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
$passenger_id = filterRequest("passenger_id");
|
||||
// Force passenger_id from JWT — never trust user-supplied passenger_id
|
||||
if ($role !== 'passenger') {
|
||||
jsonError("Only passengers can submit ratings");
|
||||
exit;
|
||||
}
|
||||
$passenger_id = $user_id;
|
||||
$driverID = filterRequest("driverID");
|
||||
$rideId = filterRequest("rideId");
|
||||
$rating = filterRequest("rating");
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
// --- استقبال المتغيرات ---
|
||||
$passenger_id = filterRequest("passenger_id");
|
||||
// Force passenger_id from JWT — only passengers can rate drivers
|
||||
if ($role !== 'passenger') {
|
||||
jsonError("Only passengers can rate drivers");
|
||||
exit;
|
||||
}
|
||||
$passenger_id = $user_id;
|
||||
$driver_id = filterRequest("driver_id");
|
||||
$ride_id = filterRequest("ride_id");
|
||||
$rating = filterRequest("rating");
|
||||
@@ -37,22 +42,11 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// --- هذا القسم خاص بأخطاء قاعدة البيانات ---
|
||||
|
||||
// 1. تسجيل الخطأ في ملف نصي على السيرفر (للمطور فقط)
|
||||
// سيتم إنشاء ملف اسمه errors.log في نفس المجلد إذا لم يكن موجوداً
|
||||
$errorMsg = "[" . date("Y-m-d H:i:s") . "] DB Error: " . $e->getMessage() . " | RideID: $ride_id \n";
|
||||
file_put_contents("errors.log", $errorMsg, FILE_APPEND);
|
||||
|
||||
// 2. إرجاع رسالة خطأ عامة للتطبيق
|
||||
error_log("[addRateToDriver] DB Error: " . $e->getMessage() . " | RideID: $ride_id");
|
||||
jsonError("Database Error: Could not save rating");
|
||||
|
||||
} catch (Exception $e) {
|
||||
// --- هذا القسم خاص بالأخطاء العامة الأخرى ---
|
||||
|
||||
$errorMsg = "[" . date("Y-m-d H:i:s") . "] General Error: " . $e->getMessage() . "\n";
|
||||
file_put_contents("errors.log", $errorMsg, FILE_APPEND);
|
||||
|
||||
jsonError("Error: " . $e->getMessage());
|
||||
error_log("[addRateToDriver] General Error: " . $e->getMessage());
|
||||
jsonError("Error: Could not save rating");
|
||||
}
|
||||
?>
|
||||
@@ -17,7 +17,8 @@ try {
|
||||
|
||||
// ── 1. Input & Validation ──────────────────────────────────────
|
||||
$rideId = filterRequest("id");
|
||||
$driverId = filterRequest("driver_id");
|
||||
// Force driver_id from JWT — never trust user-supplied driver_id
|
||||
$driverId = $user_id;
|
||||
$status = filterRequest("status"); // القيمة التي يرسلها التطبيق: 'accepted'
|
||||
$passengerToken = filterRequest("passengerToken");
|
||||
|
||||
|
||||
@@ -57,7 +57,9 @@ $start_location = filterRequest("start_location");
|
||||
$end_location = filterRequest("end_location");
|
||||
$price = filterRequest("price");
|
||||
$price_token = filterRequest("price_token");
|
||||
$passenger_id = filterRequest("passenger_id");
|
||||
|
||||
// Force passenger_id from JWT — never trust user-supplied passenger_id
|
||||
$passenger_id = $user_id;
|
||||
$driver_id = filterRequest("driver_id") ?: 0;
|
||||
$status = filterRequest("status");
|
||||
$price_for_driver = filterRequest("price_for_driver");
|
||||
|
||||
@@ -34,7 +34,8 @@ define('WALLET_PAYMENT_URL', 'https://walletintaleq.intaleq.xyz/v1/main/ride/pay
|
||||
// 1. Receive Raw Parameters (NO price from client)
|
||||
// ============================================================
|
||||
$rideId = filterRequest("rideId");
|
||||
$driver_id = filterRequest("driver_id");
|
||||
// Force driver_id from JWT — never trust user-supplied driver_id
|
||||
$driver_id = $user_id;
|
||||
$passengerId = filterRequest("passengerId");
|
||||
$newStatus = filterRequest("status"); // Expected: "Finished"
|
||||
$actualDistance = filterRequest("actualDistance");
|
||||
|
||||
@@ -25,12 +25,13 @@ try {
|
||||
$limiter = new RateLimiter($redis);
|
||||
$limiter->enforce(RateLimiter::identifier($user_id ?? null), 'upload');
|
||||
|
||||
$driverID = filterRequest("driverID");
|
||||
uploadLog("📥 Received driverID: $driverID");
|
||||
// Force driverID from JWT — never trust user-supplied driverID
|
||||
$driverID = $user_id;
|
||||
uploadLog("📥 Using JWT driverID: $driverID");
|
||||
|
||||
if (empty($driverID)) {
|
||||
uploadLog("❌ Driver ID is missing.", 'ERROR');
|
||||
jsonError('Driver ID is required.', 400);
|
||||
uploadLog("❌ Driver ID from JWT is missing.", 'ERROR');
|
||||
jsonError('Authentication required.', 400);
|
||||
}
|
||||
|
||||
// 2. استخدام دالة الرفع الآمنة (MIME check, random name, 5MB limit)
|
||||
@@ -47,8 +48,9 @@ try {
|
||||
uploadLog("✅ File moved successfully to: " . $uploadResult['path']);
|
||||
|
||||
// 3. تحديث قاعدة البيانات ديناميكياً
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'api.siromove.com';
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http";
|
||||
// Use configured domain instead of Host header to prevent host header injection
|
||||
$host = getenv('APP_DOMAIN') ?: 'api.siromove.com';
|
||||
$protocol = 'https';
|
||||
$linkImage = "$protocol://$host/siro/portrate_captain_image/" . $new_filename;
|
||||
|
||||
// تأكد من أن الاتصال قادم من connect.php أو اجلبه
|
||||
|
||||
Reference in New Issue
Block a user