# إجراءات عملية - البدء الفوري بالإصلاحات **تاريخ التحديث:** 16 يونيو 2026 **الأولوية:** 🔴 حرج جداً --- ## المرحلة 1️⃣: الإجراءات الفورية (اليوم الأول - 4 ساعات) ### ✅ الخطوة 1: تعطيل نقاط نهاية المحفظة الخطيرة **السبب:** منع الاحتيال المالي الفوري ```bash # نسخ احتياطية أولاً cp /walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/add.php \ /walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/add.php.bak cp /walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/addFromAdmin.php \ /walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/addFromAdmin.php.bak ``` **التعطيل المؤقت:** ```php 'error', 'message' => 'Wallet service temporarily disabled for security updates', 'eta' => '2026-06-17 00:00:00 UTC' ]); exit; ?> ``` --- ### ✅ الخطوة 2: إنشاء endpoint جديد في Backend **الموقع:** `backend/wallet/add.php` (جديد) ```php verifyAccessToken($matches[1]); } catch (Exception $e) { http_response_code(401); jsonError('Invalid or expired token', 401); } // 2️⃣ التحقق من الدور (التفويض) if ($decoded->role !== 'driver') { http_response_code(403); jsonError('Only drivers can add funds', 403); } $driverID = (int) $decoded->id; $amount = (float) filterRequest('amount'); $source = filterRequest('source'); // 3️⃣ تحديد السرعة $limiter = new RateLimiter($redis); try { $limiter->enforce("wallet_add_" . $driverID, 'add'); } catch (Exception $e) { http_response_code(429); jsonError('Too many requests. Please try again later.', 429); } // 4️⃣ التحقق من المبلغ if ($amount <= 0) { jsonError('Amount must be greater than 0', 400); } if ($amount > 10000) { jsonError('Amount cannot exceed 10,000', 400); } // 5️⃣ تسجيل التدقيق securityLog("Driver wallet add request", [ 'driver_id' => $driverID, 'amount' => $amount, 'source' => $source, 'timestamp' => date('Y-m-d H:i:s') ]); // 6️⃣ حفظ في قاعدة البيانات المحلية أولاً $con = Database::get('main'); $stmt = $con->prepare( "INSERT INTO driver_wallet_requests (driver_id, amount, source, status) VALUES (?, ?, ?, 'pending')" ); $stmt->execute([$driverID, $amount, $source]); $requestID = $con->lastInsertId(); // 7️⃣ استدعاء خادم المحفظة عبر S2S API $walletConnector = new WalletConnector(); try { $response = $walletConnector->call('ride/driverWallet/add_s2s', [ 'driver_id' => $driverID, 'amount' => $amount, 'source' => $source, 'request_id' => $requestID, 'backend_id' => getenv('BACKEND_ID'), ]); // ✅ النجاح $stmt = $con->prepare( "UPDATE driver_wallet_requests SET status = 'completed' WHERE id = ?" ); $stmt->execute([$requestID]); jsonSuccess(['message' => 'Funds added successfully']); } catch (Exception $e) { // فشل العملية - سجل الخطأ $stmt = $con->prepare( "UPDATE driver_wallet_requests SET status = 'failed', error = ? WHERE id = ?" ); $stmt->execute([$e->getMessage(), $requestID]); securityLog("Wallet S2S call failed", [ 'driver_id' => $driverID, 'error' => $e->getMessage() ]); http_response_code(500); jsonError('Failed to process payment', 500); } } catch (Exception $e) { securityLog("Wallet endpoint error: " . $e->getMessage()); http_response_code(500); jsonError('Internal server error', 500); } ?> ``` --- ### ✅ الخطوة 3: إنشاء فئة WalletConnector آمنة **الموقع:** `backend/core/WalletConnector.php` (جديد) ```php walletUrl = getenv('WALLET_API_URL') ?? 'https://walletintaleq.intaleq.xyz/v2/main/'; $this->hmacSecret = getenv('WALLET_HMAC_SECRET'); $this->backendID = getenv('BACKEND_ID'); if (!$this->walletUrl || !$this->hmacSecret || !$this->backendID) { throw new Exception("Missing wallet configuration"); } } /** * استدعاء API خادم المحفظة بأمان (S2S) */ public function call($endpoint, $data) { // ✅ أضف timestamp ونonce لمنع Replay Attacks $data['timestamp'] = time(); $data['nonce'] = bin2hex(random_bytes(16)); $data['backend_id'] = $this->backendID; // ✅ فرز البيانات ksort($data); // ✅ إنشاء JSON payload $payload = json_encode($data); // ✅ إنشاء توقيع HMAC $signature = hash_hmac('sha256', $payload, $this->hmacSecret); // ✅ إرسال الطلب $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $this->walletUrl . $endpoint, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $this->timeout, // ✅ رؤوس HTTP آمنة CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'X-Signature: ' . $signature, 'X-Timestamp: ' . $data['timestamp'], 'X-Backend-ID: ' . $this->backendID, 'User-Agent: SiroBackend/1.0', ], // ✅ تأمين SSL/TLS CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_CAINFO => '/etc/ssl/certs/ca-bundle.crt', ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); // ✅ فحص الأخطاء if ($curlError) { throw new Exception("CURL Error: $curlError"); } // ✅ فحص رمز HTTP if ($httpCode !== 200) { throw new Exception("Wallet API returned HTTP $httpCode: $response"); } // ✅ فحص الاستجابة $decoded = json_decode($response, true); if ($decoded === null) { throw new Exception("Invalid JSON response from wallet"); } if ($decoded['status'] !== 'success') { throw new Exception("Wallet error: " . ($decoded['message'] ?? 'Unknown')); } return $decoded; } } ?> ``` --- ### ✅ الخطوة 4: تعديل طريقة الترحيل **قاعدة البيانات الجديدة:** ```sql -- جديد: جدول لتتبع طلبات إضافة الأموال CREATE TABLE driver_wallet_requests ( id INT AUTO_INCREMENT PRIMARY KEY, driver_id INT NOT NULL, amount DECIMAL(10, 2) NOT NULL, source VARCHAR(50), status ENUM('pending', 'completed', 'failed') DEFAULT 'pending', error TEXT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (driver_id) REFERENCES driver(id), INDEX (driver_id, status), INDEX (created_at) ); -- ملف .env جديد (اضف هذه المتغيرات) # wallet configuration WALLET_API_URL=https://walletintaleq.intaleq.xyz/v2/main/ WALLET_HMAC_SECRET= BACKEND_ID=siromove-backend-01 ``` --- ## المرحلة 2️⃣: إصلاح التشفير (اليوم الثاني - 4 ساعات) ### ✅ الخطوة 5: تعديل encrypt_decrypt.php **الملف:** `backend/encrypt_decrypt.php` سأنشئ نسخة محدثة آمنة: ```php key = $key; } // ✅ ضمّ IV مع النص المشفر قبل base64_encode private function addPadding($data, $blockSize = 16) { $pad = $blockSize - (strlen($data) % $blockSize); return $data . str_repeat(chr($pad), $pad); } private function removePadding($data) { $pad = ord($data[strlen($data) - 1]); if ($pad < 1 || $pad > 16) { throw new Exception("Invalid padding"); } return substr($data, 0, -$pad); } /** * تشفير البيانات بـ IV عشوائي * ✅ التحسين: IV عشوائي لكل تشفير */ public function encryptData($plainText) { try { $plainText = mb_convert_encoding($plainText, 'UTF-8'); $paddedText = $this->addPadding($plainText); // ✅ توليد IV عشوائي - هذا هو الإصلاح الحرج $randomIV = openssl_random_pseudo_bytes(16, $strongRandom); if (!$strongRandom) { throw new Exception("openssl_random_pseudo_bytes failed to generate strong random"); } // تشفير البيانات $encrypted = openssl_encrypt( $paddedText, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $randomIV ); if (!$encrypted) { throw new Exception("Encryption failed"); } // ✅ ضمّ IV مع النص المشفر (IV يجب أن يكون أول 16 بايت) $encryptedWithIV = $randomIV . $encrypted; // تحويل إلى base64 return base64_encode($encryptedWithIV); } catch (Exception $e) { error_log("Encryption error: " . $e->getMessage()); throw $e; } } /** * فك التشفير - استخرج IV من البيانات المشفرة * ✅ التحسين: قراءة IV من البيانات المشفرة */ public function decryptData($encryptedData) { try { // فك base64 $encrypted = base64_decode($encryptedData, true); if (!$encrypted) { throw new Exception("Invalid base64 data"); } if (strlen($encrypted) < 16) { throw new Exception("Encrypted data too short"); } // ✅ استخرج IV من أول 16 بايت $iv = substr($encrypted, 0, 16); $ciphertext = substr($encrypted, 16); // فك التشفير $decrypted = openssl_decrypt( $ciphertext, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $iv ); if (!$decrypted) { throw new Exception("Decryption failed"); } // إزالة الـ padding $unpadded = $this->removePadding($decrypted); return $unpadded; } catch (Exception $e) { error_log("Decryption error: " . $e->getMessage()); throw $e; } } } // استخدام $encryption = new EncryptionHelper(); // ✅ التشفير $plaintext = "+20123456789"; $encrypted1 = $encryption->encryptData($plaintext); $encrypted2 = $encryption->encryptData($plaintext); echo "Encryption 1: $encrypted1\n"; echo "Encryption 2: $encrypted2\n"; echo "Different? " . ($encrypted1 !== $encrypted2 ? "YES ✅" : "NO ❌") . "\n"; // ✅ فك التشفير $decrypted = $encryption->decryptData($encrypted1); echo "Decrypted: $decrypted\n"; echo "Correct? " . ($decrypted === $plaintext ? "YES ✅" : "NO ❌") . "\n"; ?> ``` --- ## المرحلة 3️⃣: تقليل الأذونات (ساعة واحدة) ### ✅ الخطوة 6: تحديث AndroidManifest.xml ```xml ``` **السبب:** - ❌ لا يوجد استخدام فعلي لـ External Storage - ❌ لا يوجد استخدام لـ SYSTEM_ALERT_WINDOW - ⚠️ MODIFY_AUDIO_SETTINGS يمكن استبداله بـ requestAudioFocus --- ## المرحلة 4️⃣: تحديث الروابط (30 دقيقة) ### ✅ الخطوة 7: تحديث functions.php في `backend/functions.php`: ```php // ❌ احذف هذه: function getAllowedSocketUrls(): array { return [ 'http://188.68.36.205:2021', 'http://188.68.36.205:3031', 'https://location.intaleq.xyz', ]; } // ✅ استبدل بهذا: function getAllowedSocketUrls(): array { $urls = getenv('ALLOWED_SOCKET_URLS'); if ($urls) { return array_map('trim', explode(',', $urls)); } return [ 'https://location.siromove.com', // HTTPS فقط 'https://socket.siromove.com', // HTTPS فقط ]; } ``` **في .env:** ``` # Socket URLs - HTTPS only ALLOWED_SOCKET_URLS=https://location.siromove.com,https://socket.siromove.com ``` --- ## ✅ الخلاصة والجدول الزمني | المرحلة | الخطوات | المدة | التاريخ المتوقع | | ------------ | ------------------------------------------ | ------------- | --------------- | | 1 | تعطيل + Backend endpoint + WalletConnector | 4 س | اليوم (16/6) | | 2 | تحديث encrypt_decrypt.php + اختبار | 4 س | غد (17/6) | | 3 | تقليل الأذونات + نشر تطبيق | 1 س | غد (17/6) | | 4 | تحديث الروابط + اختبار | 30 د | غد (17/6) | | **الإجمالي** | - | **~9.5 ساعة** | **بحلول 17/6** |