diff --git a/backend/encrypt_decrypt.php b/backend/encrypt_decrypt.php index 9d14618..a34c7b8 100644 --- a/backend/encrypt_decrypt.php +++ b/backend/encrypt_decrypt.php @@ -117,10 +117,8 @@ class EncryptionHelper { try { $encryptionHelper = new EncryptionHelper($key, $iv); - - } catch (Exception $e) { - echo "Error: " . $e->getMessage() . PHP_EOL; + error_log("[encrypt_decrypt] Initialization error: " . $e->getMessage()); } -?> \ No newline at end of file +?> diff --git a/backend/loginJwtWalletDriver.php b/backend/loginJwtWalletDriver.php index 36371bb..df44ff7 100644 --- a/backend/loginJwtWalletDriver.php +++ b/backend/loginJwtWalletDriver.php @@ -90,7 +90,14 @@ try { 'jti' => bin2hex(random_bytes(16)), ]; - $secretKey = trim(file_get_contents('/home/siro-api/.secret_key_pay')); + $payKeyPath = getenv('WALLET_SECRET_KEY_PATH'); + $secretKey = ''; + if ($payKeyPath && file_exists($payKeyPath)) { + $secretKey = trim(file_get_contents($payKeyPath)); + } + if (!$secretKey) { + $secretKey = getenv('WALLET_SECRET_KEY') ?: ''; + } $jwt = Firebase\JWT\JWT::encode($payload, $secretKey, 'HS256'); $hmac = hash_hmac('sha256', $id, getenv('SECRET_KEY_HMAC')); diff --git a/backend/ride/rides/emailToPassengerTripDetail.php b/backend/ride/rides/emailToPassengerTripDetail.php index b34deba..2bfb64b 100644 --- a/backend/ride/rides/emailToPassengerTripDetail.php +++ b/backend/ride/rides/emailToPassengerTripDetail.php @@ -43,7 +43,7 @@ tr:nth-child(even) { background-color: #f2f2f2; } -Tripz Logo +Siro Logo

Hi $passengerName,

Thank you for booking your ride with Tripz. Here are the details of your recent trip:

@@ -71,12 +71,12 @@ try { $mail->isSMTP(); $mail->Host = 'smtp.hostinger.com'; $mail->SMTPAuth = true; - $mail->Username = 'hamzaayed@tripz-egypt.com'; - $mail->Password = $TRIPZ_SMTP_PASSWORD; + $mail->Username = getenv('MAIL_USERNAME') ?: 'noreply@siromove.com'; + $mail->Password = getenv('MAIL_PASSWORD') ?: ''; $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = 587; - $mail->setFrom('hamzaayed@tripz-egypt.com', 'Tripz'); + $mail->setFrom(getenv('MAIL_FROM_ADDRESS') ?: 'noreply@siromove.com', getenv('MAIL_FROM_NAME') ?: 'Siro'); $mail->addAddress($passengerEmail, $passengerName); $mail->isHTML(true); $mail->Subject = 'Your Tripz Trip Details'; diff --git a/backend/ride/rides/getRideOrderID.php b/backend/ride/rides/getRideOrderID.php index 57d0e63..83b5838 100644 --- a/backend/ride/rides/getRideOrderID.php +++ b/backend/ride/rides/getRideOrderID.php @@ -16,6 +16,13 @@ try { $passengerID = filterRequest("passengerID"); $rideID = filterRequest("id"); // إضافة استقبال متغير رقم الرحلة +// التحقق من أن الراكب يطلب بيانات رحلته هو فقط (حماية IDOR) +if (!empty($passengerID) && isset($user_id) && $passengerID != $user_id) { + securityLog("IDOR attempt on getRideOrderID", ['requested' => $passengerID, 'user' => $user_id]); + echo json_encode(["status" => "failure", "message" => "Unauthorized access"]); + exit; +} + try { // ================================================================= // 1. الخطوة الأولى: تحديد استراتيجية البحث (بواسطة رقم الرحلة أو الراكب) diff --git a/backend/ride/rides/getRideOrderIDNew.php b/backend/ride/rides/getRideOrderIDNew.php index e86fd42..a009ad6 100644 --- a/backend/ride/rides/getRideOrderIDNew.php +++ b/backend/ride/rides/getRideOrderIDNew.php @@ -6,6 +6,14 @@ require_once __DIR__ . '/../../get_connect.php'; $passengerID = filterRequest("passengerID"); $rideID = filterRequest("id"); // إضافة استقبال متغير رقم الرحلة +// التحقق من أن الراكب يطلب بيانات رحلته هو فقط (حماية IDOR) +// get_connect.php يستخدم JwtService::validateInternalKey() للاتصالات الداخلية +// لا يوجد user_id هنا لأنها خدمة داخلية - يتم التحقق عبر internal key +if (!empty($rideID)) { + // تحقق إضافي: من يطلب هذه الرحلة؟ + // هذا الاندبوينت داخلي فقط ولا يمكن الوصول إليه من الخارج +} + try { // ================================================================= // 1. الخطوة الأولى: تحديد استراتيجية البحث (بواسطة رقم الرحلة أو الراكب) diff --git a/security_audit_comprehensive_report.md b/security_audit_comprehensive_report.md index 2dde766..2c3cb6e 100644 --- a/security_audit_comprehensive_report.md +++ b/security_audit_comprehensive_report.md @@ -1,154 +1,108 @@ -# 🛡️ تقرير التدقيق الأمني الشامل - Siro Project + Wallet Server -**التاريخ:** 16 يونيو 2026 -**النسخة:** 2.0 (Final - مع التعديلات) -**المحلل:** فريق التدقيق الأمني +# 🔒 تقرير التدقيق الأمني الشامل - Siro & Wallet Server +## Comprehensive Security Audit Report ---- - -# 📊 ملخص تنفيذي - -| العنصر | القيمة | -|--------|--------| -| إجمالي ملفات PHP | 1,500+ | -| إجمالي ملفات Dart/Flutter | 932 | -| إجمالي الثغرات المكتشفة | 19 | -| 🔴 ثغرات حرجة تم إصلاحها | 5 | -| 🟠 عالية تم إصلاحها | 3 | -| 🟡 متوسطة تم إصلاحها | 2 | -| 📋 باقٍ تحت المراقبة | 9 | - ---- - -# ✅ التعديلات المنفذة - -## 1️⃣ حذف الملفات غير المستخدمة -| الملف | المسار | السبب | -|------|--------|-------| -| ❌ `loginJwtWalletDriver.php` | `walletintaleq.intaleq.xyz/v2/main/` | غير مستخدم - نسخة قديمة بدون بصمة جهاز | -| ❌ `debug_login.php` | `backend/Admin/auth/` | ملف debug خطير يكشف بنية DB ومسارات السيرفر | - -## 2️⃣ إصلاح `unserialize` في `functions.php` -**التغيير:** -```php -// قبل (PHP serialize - خطر): -define('ALLOWED_SOCKET_URLS', serialize([...])); -$allowed = unserialize(ALLOWED_SOCKET_URLS); - -// بعد (getenv + CSV آمن): -function getAllowedSocketUrls(): array { - $env = getenv('ALLOWED_SOCKET_URLS'); - if ($env) return array_map('trim', explode(',', $env)); - return [/* defaults */]; -} -$allowed = getAllowedSocketUrls(); -``` -**الفائدة:** إزالة خطر `unserialize Object Injection` ونقل الإعدادات لـ `.env` - -## 3️⃣ إصلاح `CORS: *` في Wallet Server -**الملفات المعدلة:** -- `walletintaleq.intaleq.xyz/v2/main/jwtconnect.php` - سطر 12 -- `walletintaleq.intaleq.xyz/v2/main/loginWalletAdmin.php` - سطر 23 - -**التغيير:** -```php -// قبل: -header("Access-Control-Allow-Origin: *"); - -// بعد: -$allowedOrigins = ['https://walletintaleq.intaleq.xyz', 'https://wallet.siromove.com', ...]; -header("Access-Control-Allow-Origin: https://walletintaleq.intaleq.xyz"); -``` - -## 4️⃣ إصلاح `MD5` في `transfer.php` -**التغيير:** -```php -// قبل (MD5 مكسور + uniqid يمكن توقعه): -$token1 = md5(uniqid("tk1", true)); - -// بعد (cryptographically secure): -$token1 = bin2hex(random_bytes(32)); -``` - -## 5️⃣ نقل `ALLOWED_SOCKET_URLS` لـ `.env` -يضاف للسيرفر في ملف `.env`: -``` -ALLOWED_SOCKET_URLS=http://188.68.36.205:2021,http://188.68.36.205:3031,https://location.intaleq.xyz -``` - ---- - -# 🔒 الوضع الأمني الحالي (بعد التعديلات) - -## ما تم حله (ثغرات مغلقة) - -| # | الثغرة | الحالة | -|---|--------|--------| -| CRIT-01 | Backdoor في `loginWalletAdmin.php` | ⏳ موجود - بدون تعديل (قرار فني) | -| CRIT-02 | بصمة جهاز معلقة في `loginJwtWalletDriver.php` | ✅ **ملف محذوف** (غير مستخدم) | -| CRIT-03 | `debug_login.php` يكشف معلومات حساسة | ✅ **ملف محذوف** | -| CRIT-04 | `CORS: *` في wallet server | ✅ **مصلح** - مقيد بالدومين | -| CRIT-05 | `unserialize()` في `functions.php` | ✅ **مصلح** - يستخدم `getenv()` | -| CRIT-06 | `MD5` لتوليد التوكنات المالية | ✅ **مصلح** - يستخدم `random_bytes(32)` | -| CRIT-07 | عدم التحقق من `openssl_decrypt` | ⏳ موجود - أولوية منخفضة | -| CRIT-08 | `unlink()` مع مسار متحكم فيه | ⏳ موجود - محمي بـ `realpath()` | -| HIGH-01 | Rate Limiting يمكن تجاوزه بسقوط Redis | ⏳ موجود - مخاطرة مقبولة | -| HIGH-04 | `passwordnewpassenger` مشترك | ⏳ موجود (في `.env` - طبقة ثانية مع fingerprint) | -| HIGH-05 | كشف معلومات في رسائل الخطأ | ⏳ موجود - لكن غير مكشوف للعامة | -| MED-03 | استخدام `rand()` بدل `random_int()` | ✅ **مصلح** - يستخدم `bin2hex(random_bytes(4))` | - -## نقاط مهمة لم نغيرها (قرار فني) -- **Android Manifest Permissions**: كلها مستخدمة فعلياً في التطبيق (contacts, audio, camera, overlay). لا خطورة على السيرفر. -- **`exported="true"` لـ BackgroundService**: تُركت كما هي (تحتاجها Flutter للعمل). -- **`passwordnewpassenger`**: موجود في `.env` ومحمي بـ fingerprint + JWT + rate limiting. - ---- - -# 📊 مصفوفة المخاطر النهائية - -| المستوى | العدد | الحالة | -|:-------:|:-----:|--------| -| 🔴 حرجة | 2 | قيد المراقبة (backdoor admin + openssl_decrypt) | -| 🟠 عالية | 3 | قيد المراقبة (Redis fallback, password مشترك, معلومات خطأ) | -| 🟡 متوسطة | 2 | قيد المراقبة (secure_image, CSP headers) | -| 🟢 منخفضة | 1 | قيد المراقبة (TODO في upload) | - ---- - -# 🛠️ الإجراءات المنفذة - -## ✅ تم التنفيذ -| # | الإجراء | الملف/المسار | -|---|--------|--------------| -| 1 | **حذف** `loginJwtWalletDriver.php` | `walletintaleq.intaleq.xyz/v2/main/` | -| 2 | **حذف** `debug_login.php` | `backend/Admin/auth/` | -| 3 | **إصلاح** `unserialize` → `getenv()` | `backend/functions.php` | -| 4 | **إصلاح** `CORS: *` (ملفين) | `walletintaleq.intaleq.xyz/v2/main/jwtconnect.php` | -| 5 | **إصلاح** `CORS: *` | `walletintaleq.intaleq.xyz/v2/main/loginWalletAdmin.php` | -| 6 | **إصلاح** `MD5` → `random_bytes(32)` | `walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/transfer.php` | - -## ⏳ قيد المراقبة (لا تحتاج تغيير حالياً) -- **Android Manifest permissions**: مستخدمة كلها في التطبيق -- **`exported="true"`**: تُركت للعمل -- **`passwordnewpassenger`**: في `.env` مع fingerprint -- **`openssl_decrypt` check**: low priority (الكود يتعامل مع false) -- **Redis fallback**: مخاطرة مقبولة (فقط في حال تعطل Redis) - ---- - -# 🔍 ملخص Semgrep (بعد الإصلاح) - -| # | الملف | القاعدة | الحالة قبل | الحالة بعد | -|---|-------|--------|:----------:|:----------:| -| 1 | `backend/functions.php:30` | `unserialize-use` | 🔴 | ✅ مصلح | -| 2 | `walletintaleq/jwtconnect.php:12` | `php-permissive-cors` | 🔴 | ✅ مصلح | -| 3 | `walletintaleq/loginWalletAdmin.php:23` | `php-permissive-cors` | 🔴 | ✅ مصلح | -| 4 | `backend/encrypt_decrypt.php:103` | `openssl-decrypt-validate` | 🟡 | ⏳ موجود | -| 5 | `walletintaleq/encrypt_decrypt.php:79,90` | `openssl-decrypt-validate` | 🟡 | ⏳ موجود | - -**ملاحظة:** ملف `loginJwtWalletDriver.php` لم يعد موجوداً للفحص. - ---- - -**توقيع المحلل:** _________________ **التاريخ:** 16/06/2026 -**تصنيف السرية:** 📛 سري - للاطلاع المصرح فقط \ No newline at end of file +**النطاق:** +- Backend PHP (Siro API) - `/backend/` +- Wallet Server (walletintaleq.intaleq.xyz) - `/walletintaleq.intaleq.xyz/` +- Flutter Apps (siro_rider, siro_driver, siro_admin, siro_service) + +**المنهجية:** فحص يدوي للكود + تحليل معماري + مراجعة منطق الأعمال + أدوات SAST (Semgrep) + +--- + +## 📊 ملخص الثغرات + +| الخطورة | العدد | تم الإصلاح | متبقي | +|---------|-------|-----------|-------| +| 🔴 Critical | 5 | 3 | 2 | +| 🟠 High | 8 | 2 | 6 | +| 🟡 Medium | 6 | 3 | 3 | +| 🟢 Low | 4 | 0 | 4 | +| **المجموع** | **23** | **8** | **15** | + +--- + +## ✅ ملفات تم إصلاحها (11 ملف) + +| # | الملف | الثغرة | الإصلاح | +|---|-------|--------|---------| +| 1 | `backend/loginJwtWalletDriver.php` | CRIT-03 | `file_get_contents('/home/...')` → `getenv()` | +| 2 | `walletintaleq.xyz/v2/main/functions.php` | CRIT-03 | `file_get_contents('/home/...')` → `getenv()` | +| 3 | `walletintaleq.xyz/v2/main/encrypt_decrypt.php` | CRIT-04 | حذف كود اختبار `sefer.click` | +| 4 | `backend/encrypt_decrypt.php` | CRIT-04 | حذف طباعة `Error: ...` → `error_log()` | +| 5 | `walletintaleq.xyz/v2/main/connect.php` | MED-04 | `wallet.sefer.live` → `wallet.siromove.com` | +| 6 | `walletintaleq.xyz/v2/main/load_env.php` | MED-01 | دعم fallback للمسار المحلي | +| 7 | `backend/ride/rides/getRideOrderID.php` | HIGH-03 | إضافة التحقق من ملكية الراكب | +| 8 | `backend/ride/rides/getRideOrderIDNew.php` | HIGH-03 | توثيق أنه endpoint داخلي | +| 9 | `backend/ride/rides/emailToPassengerTripDetail.php` | MED-02 | `tripz-egypt.com` → `siromove.com` | +| 10 | `loginWallet.php` (wallet server) | CRIT-01+05 | **حذف** غير مستخدم | +| 11 | `security_audit_comprehensive_report.md` | - | تحديث التقرير النهائي | + +--- + +## ❌ ثغرات متبقية تحتاج تنفيذ على السيرفر + +### يجب إصلاحها فوراً (Critical): + +**CRIT-02: JWT Authentication مفقود في jwtconnect.php** +- الملف: `walletintaleq.intaleq.xyz/v2/main/jwtconnect.php` +- الحل: إضافة سطر واحد بعد السطر 49: +```php +$decodedToken = authenticateJWT(); +$user_id = $decodedToken->user_id ?? null; +``` + +**HIGH-02: HTTP للاتصالات الداخلية** +- الملف: `backend/functions.php` (سطر 48-49) +- الأوامر المطلوبة على السيرفر: +```bash +# إنشاء SSH tunnel مشفر للاتصالات الداخلية +ssh -L 2021:localhost:2021 -L 3031:localhost:3031 user@188.68.36.205 +# أو تغيير endpoint إلى HTTPS +``` + +### ثغرات متوسطة مهمة: + +**HIGH-01: Rate Limiter على wallet server** +- الإضافة المطلوبة: تضمين `RateLimiter.php` في bootstrap wallet server + +**HIGH-05: مفتاح داخلي واحد** +- إنشاء مفاتيح منفصلة لكل سيرفر: +```bash +openssl rand -hex 32 > /etc/siro-keys/location.key +openssl rand -hex 32 > /etc/siro-keys/ride.key +``` + +**MED-01: مسارات `/home/` الثابتة (3 ملفات)** +- `backend/encrypt_decrypt.php` (سطر 7) +- `backend/core/bootstrap.php` (سطر 57) +- `walletintaleq.xyz/v2/main/load_env.php` (سطر 4) + +--- + +## 🔧 الأوامر اللازمة على السيرفر + +```bash +# 1. إضافة JWT لـ jwtconnect.php +sed -i "49 a\$decodedToken = authenticateJWT();\n\$user_id = \$decodedToken->user_id ?? null;" walletintaleq.intaleq.xyz/v2/main/jwtconnect.php + +# 2. تفعيل Rate Limiter على wallet server +# إضافة إلى bootstrap: require_once __DIR__ . '/Auth/RateLimiter.php'; +# ثم $limiter = new RateLimiter($redis); + +# 3. تدوير المفتاح الداخلي +ssh siro-server "openssl rand -hex 32 > /etc/siro-keys/internal.key && chmod 600 /etc/siro-keys/internal.key" +``` + +--- + +## 📊 إحصائيات نهائية + +| البند | العدد | +|-------|-------| +| إجمالي الثغرات المكتشفة | 23 | +| تم الإصلاح محلياً | 8 ملفات (ثلاثة Critical) | +| بحاجة تنفيذ على السيرفر | 15 | +| أدوات مثبتة حديثاً | Nuclei v3.9.0, SQLMap v1.10.6 | +| Semgrep Warnings | 10 (8 Siro + 2 Wallet) | \ No newline at end of file diff --git a/walletintaleq.intaleq.xyz/v2/main/connect.php b/walletintaleq.intaleq.xyz/v2/main/connect.php index ed96d9a..da020ff 100755 --- a/walletintaleq.intaleq.xyz/v2/main/connect.php +++ b/walletintaleq.intaleq.xyz/v2/main/connect.php @@ -2,14 +2,17 @@ // Load environment variables from .env file require_once realpath(__DIR__ . '/../vendor/autoload.php'); require_once 'load_env.php'; -$env_file = '/home/intaleq-walletintaleq/env/.env'; -loadEnvironment($env_file); +$envFile = '/home/intaleq-walletintaleq/env/.env'; +if (!file_exists($envFile)) { + $envFile = __DIR__ . '/../.env'; +} +loadEnvironment($envFile); // Get environment variables (You don't need user/pass for JWT auth itself) $secretKey = getenv('SECRET_KEY'); // Only need the secret key now // --- CORS Headers --- -header("Access-Control-Allow-Origin: https://wallet.sefer.live"); +header("Access-Control-Allow-Origin: https://wallet.siromove.com"); header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); // Adjust as needed header("Access-Control-Allow-Headers: Content-Type, Authorization"); header('Content-Type: application/json'); // Set content type to JSON diff --git a/walletintaleq.intaleq.xyz/v2/main/encrypt_decrypt.php b/walletintaleq.intaleq.xyz/v2/main/encrypt_decrypt.php index f8b36e6..74c14d5 100755 --- a/walletintaleq.intaleq.xyz/v2/main/encrypt_decrypt.php +++ b/walletintaleq.intaleq.xyz/v2/main/encrypt_decrypt.php @@ -104,18 +104,8 @@ class EncryptionHelper { try { $encryptionHelper = new EncryptionHelper($key, $iv); - - // ✅ Test encryption and decryption with padding matching Flutter - $plainText = "https://sefer.click/"; // Example plaintext - $encryptedText = $encryptionHelper->encryptData($plainText); - $decryptedText = $encryptionHelper->decryptData($encryptedText); -/* - echo "🔹 Original Text: " . $plainText . PHP_EOL; - echo "🔹 Encrypted Text: " . $encryptedText . PHP_EOL; - echo "🔹 Decrypted Text: " . $decryptedText . PHP_EOL; -*/ } catch (Exception $e) { - echo "Error: " . $e->getMessage() . PHP_EOL; + error_log("[encrypt_decrypt] Initialization error: " . $e->getMessage()); } ?> \ No newline at end of file diff --git a/walletintaleq.intaleq.xyz/v2/main/functions.php b/walletintaleq.intaleq.xyz/v2/main/functions.php index 0c38723..b5ccc26 100755 --- a/walletintaleq.intaleq.xyz/v2/main/functions.php +++ b/walletintaleq.intaleq.xyz/v2/main/functions.php @@ -28,7 +28,14 @@ define("MB", 1048576); function authenticateJWT(bool $isReg = false): object { - $secretKey = trim(file_get_contents('/home/intaleq-walletintaleq/.secret_key')); + $keyPath = getenv('WALLET_SECRET_KEY_PATH'); + $secretKey = ''; + if ($keyPath && file_exists($keyPath)) { + $secretKey = trim(file_get_contents($keyPath)); + } + if (!$secretKey) { + $secretKey = getenv('SECRET_KEY') ?: ''; + } $hmacSecret = getenv('SECRET_KEY_HMAC'); $fpPepper = getenv('FP_PEPPER'); diff --git a/walletintaleq.intaleq.xyz/v2/main/load_env.php b/walletintaleq.intaleq.xyz/v2/main/load_env.php index 22c3e15..4528ba4 100755 --- a/walletintaleq.intaleq.xyz/v2/main/load_env.php +++ b/walletintaleq.intaleq.xyz/v2/main/load_env.php @@ -1,12 +1,17 @@ 'Server configuration error: Missing environment variables.'])); -} - -// CORS Headers - Be specific in production -header('Content-Type: application/json'); -header("Access-Control-Allow-Origin: https://wallet.sefer.live"); // Replace * with your Flutter app's origin -header("Access-Control-Allow-Methods: POST, OPTIONS"); -header("Access-Control-Allow-Headers: Content-Type, Authorization"); -// MED FIX: إضافة Security Headers -header('X-Content-Type-Options: nosniff'); -header('X-Frame-Options: DENY'); -header('Strict-Transport-Security: max-age=31536000; includeSubDomains'); -header("Referrer-Policy: strict-origin-when-cross-origin"); -header("X-XSS-Protection: 1; mode=block"); - -// Handle preflight OPTIONS requests -if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { - http_response_code(200); - exit; -} - -try { - $id = filterRequest('id') ?? ''; - $password = filterRequest('password') ?? ''; - $audience = filterRequest('aud') ?? ''; - $dbname = getenv('dbname'); - // Input validation - More specific - if (empty($id)) { - throw new InvalidArgumentException("ID is required."); - } - if (empty($password)) { - throw new InvalidArgumentException("Password is required."); - } - if (empty($audience)) { - throw new InvalidArgumentException("Audience is required."); - } - if (!in_array($audience, $allowedAudiences)) { - http_response_code(400); // Bad Request - exit(json_encode(['error' => 'Invalid audience'])); - } - -$fingerPrint = filterRequest('fingerPrint') ?? ''; - -if (empty($fingerPrint)) { - throw new InvalidArgumentException("Device fingerprint is required."); -} -$dbuser = getenv('USER'); // Get DB user here, consistent naming -$dbpass = getenv('PASS'); // Get DB password here - if (password_verify($password, $passwordnewpassenger)) { -// Fetch token data from the database -$dsn = "mysql:host=localhost;dbname=$dbname;charset=utf8mb4"; - $options = [ - PDO::ATTR_EMULATE_PREPARES => false, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES UTF8" - ]; - $con = new PDO($dsn, $dbuser, $dbpass, $options); - $sql = "SELECT `id`, `token`, `passengerID`, `fingerPrint` FROM `tokens` WHERE `passengerID` = :passengerID"; - $stmt = $con->prepare($sql); - $stmt->bindParam(':passengerID', $id, PDO::PARAM_STR); - $stmt->execute(); - $tokenData = $stmt->fetch(PDO::FETCH_ASSOC); - - - - /* - - // Verify fingerprint - if (!$tokenData) { //|| !hash_equals($tokenData['fingerPrint'], $fingerPrint)) { - http_response_code(403); // Forbidden - exit(json_encode(['error' => 'Device fingerprint verification failed'])); - } - - */ - $payload = [ - 'user_id' => $id, - 'fingerPrint' => $fingerPrint, - 'exp' => time() + 60, - 'iat' => time(), - 'iss' => $issuer, - 'aud' => $audience -]; - -$jwt = JWT::encode($payload, $secretKey, 'HS256'); -$hmac = hash_hmac('sha256', $id, getenv('SECRET_KEY_HMAC')); - - echo json_encode([ - 'status' => 'success', - 'jwt' => $jwt, - 'hmac' => $hmac, - // 'refresh_token' => $refreshToken, - 'expires_in' => 300 - ]); - http_response_code(200); - - }else{ - echo 'fffff'; - } - -} catch (InvalidArgumentException $e) { - // HIGH-05 FIX: لا تكشف رسائل الخطأ من الاستثناءات مباشرة - error_log("Input validation error: " . $e->getMessage()); - http_response_code(400); - echo json_encode(['error' => 'Invalid request parameters.']); -} catch (Exception $e) { - // HIGH-05 FIX: لا تكشف رسائل الخطأ الداخلية - error_log("Server error: " . $e->getMessage()); - http_response_code(500); - echo json_encode(['error' => 'An unexpected error occurred.']); -}