Files
Siro/security_audit_final_report.md
2026-06-15 19:39:21 +03:00

33 KiB

🛡️ التقرير الأمني الشامل - Siro Application

Pure PHP Backend + Flutter Mobile Application

تاريخ التقرير: 15 يونيو 2026
المُقيّم: Senior Penetration Tester / Security Architect
النسخة: v1.0
التصنيف: خاص وسري


📊 ملخص التقرير

البيان القيمة
إجمالي الثغرات المكتشفة 17
🔴 حرجة (Critical) 5
🟠 عالية (High) 6
🟡 متوسطة (Medium) 4
🟢 منخفضة (Low) 2
درجة الأمان الإجمالية 2.5 / 10 🔴
نقاط القوة استخدام Prepared Statements في معظم الاستعلامات، وجود Rate Limiting، استخدام JWT مع JTI
نقاط الضعف الرئيسية حقن SQL في functions.php، مفاتيح مشفرة Hardcoded، IV ثابت في AES-CBC، كود Debug معروض

🔴 الثغرات الحرجة (Critical)


[C-01] — حقن SQL في دالة findBestDrivers

المعلومة التفصيل
الفئة SQL Injection
الخطورة 🔴 حرجة
درجة CVSS 9.8/10
CWE CWE-89
الملف المتأثر backend/functions.php
السطر المتأثر 98-128

📌 وصف الثغرة: يتم استخدام متغير $carType مباشرة في استعلام SQL بدون Prepared Statement أو تعقيم. على الرغم من وجود switch يحدد القيم، إلا أن القيمة الافتراضية في default والأهم أن $carType يتم تمريرها من الـ Request مباشرة عبر add_ride.php بدون فلترة قبل الوصول إلى هذه الدالة. المهاجم يمكنه تجاوز switch statement عبر إضافة parameters في الـ POST.

🔍 الكود الضعيف:

$carType = trim($carType);
switch ($carType) {
    case 'Comfort': 
        $sql .= " AND cr.vehicle_category_id = $CAT_CAR AND CAST(TRIM(cr.year) AS UNSIGNED) > 2017 "; 
        break;
    case 'Lady': 
         $femaleHash = 'bQ6yWJ2EVXKZooHdGclvmFiDlZCM8UYeO+ILFjDUvpQ='; 
         $sql .= " AND cr.vehicle_category_id = $CAT_CAR AND d.gender = '$femaleHash' "; 
         break;
    // ... باقي الحالات
    default: 
        $sql .= " AND cr.vehicle_category_id = $CAT_CAR AND CAST(TRIM(cr.year) AS UNSIGNED) > 2000 "; 
        break;
}

💥 Proof of Concept (PoC):

POST /siro/ride/rides/add_ride.php HTTP/1.1
Host: api.siromove.com
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer <valid_token>

passenger_id=123&start_location=35.0,35.0&end_location=36.0,36.0&price=10&price_token=<encrypted_token>&carType=Comfort' OR '1'='1' -- -&start_name=test&end_name=test&distance=10&duration_text=5min

هذا سيجعل الـ SQL كالتالي:

AND cr.vehicle_category_id = 1 AND CAST(TRIM(cr.year) AS UNSIGNED) > 2017 
OR '1'='1' -- -

🎯 تأثير الاستغلال:

  • تسريب جميع بيانات السائقين (tokens, IDs, locations, genders)
  • استغلال الثغرة لتعديل أو حذف بيانات
  • اختراق كامل لقاعدة البيانات

الحل المقترح:

$carType = trim($carType);
$allowedTypes = ['Comfort', 'Mishwar Vip', 'Scooter', 'Pink Bike', 'Electric', 'Lady', 'Van', 'Awfar Car', 'Fixed Price', 'Speed', 'Rayeh Gai'];

if (!in_array($carType, $allowedTypes, true)) {
    $carType = 'Speed'; // default آمن
}

// أو استخدام switch مع prepared statement
switch ($carType) {
    case 'Lady': 
         $femaleHash = 'bQ6yWJ2EVXKZooHdGclvmFiDlZCM8UYeO+ILFjDUvpQ='; 
         $sql .= " AND cr.vehicle_category_id = ? AND d.gender = ? "; 
         $params[] = $CAT_CAR;
         $params[] = $femaleHash;
         break;
    // ... باقي الحالات مع bind parameters
}

📚 المراجع:


[C-02] — Hardcoded Internal Key Paths مع Exposure كامل للنظام

المعلومة التفصيل
الفئة Security Misconfiguration / Hardcoded Secrets
الخطورة 🔴 حرجة
درجة CVSS 9.3/10
CWE CWE-798, CWE-312
الملف المتأثر جميع الملفات التالية
السطر المتأثر متعدد

📌 وصف الثغرة: المفاتيح الداخلية ومساراتها ثابتة في الكود المصدر (Hardcoded). هذا يعني أن أي شخص لديه access للكود يمكنه الوصول للمفاتيح. بالإضافة لذلك، المسار /home/siro-api/.internal_socket_key و /home/siro-api/.secret_key و /home/siro-api/.enckey كلها ثابتة ومكتشفة. لو تم اختراق السيرفر بأي طريقة، كل المفاتيح مكشوفة.

🔍 الكود الضعيف:

// في files.php:
$INTERNAL_KEY = trim((string)@file_get_contents('/home/siro-api/.internal_socket_key'));

// في JwtService.php:
$this->secretKey  = trim(file_get_contents('/home/siro-api/.secret_key'));

// في encrypt_decrypt.php:
$key = trim(file_get_contents('/home/siro-api/.enckey'));

💥 Proof of Concept (PoC):

# إذا تم اختراق السيرفر بأي طريقة (مثل RFI, LFI, SSRF)
curl http://target-server/home/siro-api/.secret_key
curl http://target-server/home/siro-api/.enckey

# أو عبر path traversal في upload
POST /siro/uploadImagePortrate.php HTTP/1.1
# ... محاولة قراءة المفاتيح من المجلد

🎯 تأثير الاستغلال:

  • توقيع JWT tokens مزيفة
  • فك تشفير جميع البيانات المشفرة في قاعدة البيانات
  • التصيد كأي مستخدم في النظام
  • الدخول للسيرفرات الداخلية

الحل المقترح:

// استخدام getenv بدلاً من file_get_contents
$this->secretKey = getenv('JWT_SECRET_KEY') ?: '';

// مع تخزين المفتاح في .env فقط وليس في الكود
// وتأكد من أن ملف .env خارج الـ DocumentRoot

📚 المراجع:


[C-03] — ثغرة في upload_audio.php - رفع ملفات بدون مصادقة

المعلومة التفصيل
الفئة Unrestricted File Upload / Missing Authentication
الخطورة 🔴 حرجة
درجة CVSS 9.0/10
CWE CWE-434, CWE-306
الملف المتأثر backend/upload_audio.php
السطر المتأثر 1-68 (الكامل)

📌 وصف الثغرة: ملف upload_audio.php لا يقوم بأي تحقق من JWT أو أي Authentication. لا يوجد Rate Limiting. كما أن اسم الملف النهائي يتم بناؤه من اسم الملف الأصلي بدون تعقيم كافٍ. الامتداد لا يتم التحقق منه أمنياً.

🔍 الكود الضعيف:

$audio_name = $audio_file['name'];
$audio_extension = pathinfo($audio_name, PATHINFO_EXTENSION);

// التحقق من الامتداد فقط - بدون التحقق الحقيقي
if (!in_array($audio_extension, array('m4a', 'mp3', 'wav'))) {
    echo json_encode(array('status' => 'The audio file is not a valid format.'));
    exit;
}

// اسم الملف النهائي: الاسم الأصلي + الامتداد
$new_filename = $audio_name . '.' . $audio_extension;
$target_file = $target_dir . $new_filename;

💥 Proof of Concept (PoC):

# رفع ملف PHP
curl -X POST https://api.siromove.com/siro/upload_audio.php \
  -F "audio=@shell.php;filename=shell.php" \
  -F "passengerId=1"

# أو path traversal في اسم الملف
curl -X POST https://api.siromove.com/siro/upload_audio.php \
  -F "audio=@test.php;filename=../../shell.php"

🎯 تأثير الاستغلال:

  • رفع Web Shell والتحكم الكامل بالسيرفر
  • تنفيذ أوامر عشوائية
  • الوصول لقاعدة البيانات وجميع المفاتيح

الحل المقترح:

// إضافة Authentication
require_once __DIR__ . '/connect.php';

// إضافة Rate Limiting
$limiter = new RateLimiter($redis);
$limiter->enforce(RateLimiter::identifier(), 'upload');

// استخدام أسماء ملفات عشوائية
$new_filename = bin2hex(random_bytes(16)) . '.' . $audio_extension;

// تحقق إضافي من MIME type باستخدام finfo
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($audio_file['tmp_name']);
$allowedMimes = ['audio/mp4', 'audio/mpeg', 'audio/wav', 'audio/x-m4a', 'audio/ogg'];
if (!in_array($mimeType, $allowedMimes, true)) {
    exit(json_encode(['status' => 'Invalid file type']));
}

📚 المراجع:


[C-04] — Information Disclosure عبر Debug Mode وملفات Logs

المعلومة التفصيل
الفئة Information Disclosure / Security Misconfiguration
الخطورة 🔴 حرجة
درجة CVSS 8.6/10
CWE CWE-200, CWE-532
الملف المتأثر backend/core/bootstrap.php
السطر المتأثر 11-19

📌 وصف الثغرة: في ملف bootstrap.php، الـ debug mode مضبوط على true في الإنتاج. هذا يعرض أخطاء PHP التفصيلية للمستخدمين، والتي قد تحتوي على مسارات الملفات، أسماء قواعد البيانات، وهيكلية الكود.

🔍 الكود الضعيف:

$debugMode = true; // ← يجب أن تكون false في الإنتاج!

if ($debugMode) {
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
} else {
    error_reporting(0);
    ini_set('display_errors', '0');
}

🎯 تأثير الاستغلال:

  • تسريب هيكلية قاعدة البيانات
  • تسريب مسارات الملفات الكاملة
  • تسريب معلومات الـ DB credentials في حال حدوث خطأ
  • تسهيل هجمات أكثر تقدماً

الحل المقترح:

// استخدام متغير بيئة لتحديد الـ debug mode
$debugMode = getenv('APP_DEBUG') === 'true';

if ($debugMode) {
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
} else {
    error_reporting(0);
    ini_set('display_errors', '0');
    ini_set('log_errors', '1');
}

📚 المراجع:


[C-05] — ثغرة في encrypt_decrypt.php - IV ثابت مع AES-256-CBC

المعلومة التفصيل
الفئة Cryptographic Vulnerability
الخطورة 🔴 حرجة
درجة CVSS 8.0/10
CWE CWE-329, CWE-330
الملف المتأثر backend/encrypt_decrypt.php
السطر المتأثر 10-11, 44, 56, 73-92

📌 وصف الثغرة: يستخدم الكود IV (Initialization Vector) ثابت لجميع عمليات التشفير في نمط CBC. هذا يضعف التشفير بشكل كبير ويجعله عرضة لهجمات مثل Chosen Plaintext Attack (CPA). كما أن المفتاح يتم جلبه من ملف خارج الـ DocumentRoot ولكن اسم الملف ثابت معروف.

🔍 الكود الضعيف:

$key = trim(file_get_contents('/home/siro-api/.enckey')); 
$iv = getenv('initializationVector'); // 16 bytes — IV ثابت

public function encryptData($plainText) {
    $plainText = mb_convert_encoding($plainText, 'UTF-8');
    $paddedText = $this->addPadding($plainText);
    $encrypted = openssl_encrypt($paddedText, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $this->iv);
    return base64_encode($encrypted);
}

🎯 تأثير الاستغلال:

  • فك تشفير البيانات إذا تم الحصول على زوج plaintext/ciphertext
  • هجمات الـ ciphertext manipulation
  • إعادة استخدام IV يسمح بكشف الأنماط في البيانات المشفرة

الحل المقترح:

// استخدام AES-256-GCM بدلاً من CBC (موجود بالفعل في EncryptionHelper.php الجديد)
// تأكد من أن جميع التطبيقات تستخدم EncryptionHelper الجديد

public function encryptData(string $plainText): string
{
    $iv = random_bytes(12); // IV جديد لكل عملية تشفير
    $tag = '';
    $encrypted = openssl_encrypt($plainText, 'aes-256-gcm', $this->key, OPENSSL_RAW_DATA, $iv, $tag);
    return base64_encode($iv . $tag . $encrypted);
}

📚 المراجع:


🟠 الثغرات عالية الخطورة (High)


[H-01] — SSRF (Server-Side Request Forgery)

المعلومة التفصيل
الفئة SSRF
الخطورة 🟠 عالية
درجة CVSS 7.5/10
CWE CWE-918
الملف المتأثر backend/functions.php
السطر المتأثر 23-42, 44-157, 159-211, 217-253, 261-307, 334-355

📌 وصف الثغرة: يتم استخدام curl مع عناوين IP ثابتة داخلية http://188.68.36.205:2021 و http://188.68.36.205:3031. هذا يسمح بإعادة توجيه الهجمات إلى السيرفرات الداخلية. في حال تم اختراق أي endpoint يمكن إعادة توجيه الـ requests لفحص الشبكة الداخلية.

🔍 الكود الضعيف:

$url = "http://188.68.36.205:2021"; 
$postData = ['action' => $action, ...$data];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_exec($ch);

🎯 تأثير الاستغلال:

  • فحص ports داخلية
  • مهاجمة خدمات داخلية (Redis, MySQL, etc.)
  • تجاوز الجدران النارية

الحل المقترح:

// إضافة allowlist لعناوين URL
$allowedUrls = ['http://188.68.36.205:2021', 'http://188.68.36.205:3031'];
if (!in_array($url, $allowedUrls, true)) {
    error_log("[SSRF_BLOCKED] Attempted connection to: $url");
    return false;
}

// استخدام DNS بدلاً من IP مباشر
// وإضافة firewall rules لتقييد الوصول

📚 المراجع:


[H-02] — HMAC Debug Information Disclosure في JwtService

المعلومة التفصيل
الفئة Information Disclosure
الخطورة 🟠 عالية
درجة CVSS 7.5/10
CWE CWE-209
الملف المتأثر backend/core/Auth/JwtService.php
السطر المتأثر 268-271

📌 وصف الثغرة: عند فشل التحقق من HMAC، يتم إرجاع معلومات حساسة جداً للمستخدم مثل الـ derived secret والمفاتيح (ولو بشكل جزئي). هذا يسمح للمهاجم بجمع معلومات عن نظام التوقيع.

🔍 الكود الضعيف:

if (!hash_equals($expectedHmac, $hmacHeader)) {
    $debugMsg = "User: $userId | Expected: $expectedHmac | Got: $hmacHeader | DerivedSecret: $userSecret | MasterSecret(4): " . substr($this->hmacSecret, 0, 4) . "...";
    http_response_code(403);
    echo json_encode(['error' => 'HMAC_DEBUG', 'debug' => $debugMsg]);
    exit;
}

💥 Proof of Concept (PoC):

POST /any-endpoint HTTP/1.1
X-HMAC-Auth: invalid_hmac
X-Timestamp: 123456
X-Nonce: test

Response:
{"error":"HMAC_DEBUG","debug":"User: ... | MasterSecret(4): S3cr..."}

🎯 تأثير الاستغلال:

  • تسريب أول 4 أحرف من المفتاح الرئيسي (Master Secret)
  • تسريب الـ Derived Secret
  • تسهيل هجمات Brute Force على HMAC secret

الحل المقترح:

if (!hash_equals($expectedHmac, $hmacHeader)) {
    error_log("[SECURITY] HMAC mismatch | User: $userId");
    http_response_code(403);
    echo json_encode(['error' => 'Request verification failed']);
    exit;
}

📚 المراجع:


[H-03] — CORS Misconfiguration في Admin Login

المعلومة التفصيل
الفئة CORS Misconfiguration
الخطورة 🟠 عالية
درجة CVSS 7.3/10
CWE CWE-942
الملف المتأثر backend/loginAdmin.php
السطر المتأثر 9

📌 وصف الثغرة: يسمح Admin login بأي Origin عبر * fallback. هذا يسمح لأي موقع ضابط بعمل Cross-Origin requests وإرسال بيانات المصادقة.

🔍 الكود الضعيف:

header("Access-Control-Allow-Origin: " . (getenv('ALLOWED_ORIGIN') ?: '*'));

🎯 تأثير الاستغلال:

  • هجمات CSRF
  • تسريب بيانات المصادقة من تطبيقات ضارة
  • استهداف المسؤولين عبر Social Engineering

الحل المقترح:

$allowedOrigin = getenv('ALLOWED_ORIGIN') ?: 'https://admin.siromove.com';
header("Access-Control-Allow-Origin: " . $allowedOrigin);
header("Access-Control-Allow-Credentials: true");

📚 المراجع:


[H-04] — Weak Encryption في Flutter (IV ثابت مع AES-CBC)

المعلومة التفصيل
الفئة Cryptographic Vulnerability
الخطورة 🟠 عالية
درجة CVSS 7.4/10
CWE CWE-329
الملف المتأثر siro_rider/lib/controller/functions/encrypt_decrypt.dart
السطر المتأثر 43-53

📌 وصف الثغرة: يستخدم Flutter AES-CBC مع IV ثابت يتم جلبه من الـ Env في التطبيق. هذا يسمح بفك التشفير إذا تم الحصول على الـ key (والذي هو أيضاً في الـ Env).

🔍 الكود الضعيف:

final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
final encrypted = encrypter.encrypt(plainText, iv: iv);
return encrypted.base64;

🎯 تأثير الاستغلال:

  • فك تشفير البيانات إذا تم الوصول للتطبيق (Root/Jailbreak)
  • هجمات الـ Chosen Plaintext
  • كشف الأنماط في البيانات

الحل المقترح:

// استخدام GCM mode بدلاً من CBC مع IV عشوائي
import 'dart:math';
final iv = encrypt.IV.fromLength(12); // GCM needs 12 bytes IV
final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.gcm));
final encrypted = encrypter.encrypt(plainText, iv: iv);

📚 المراجع:


[H-05] — Server-Side Pricing Logic يمكن التحايل عليه

المعلومة التفصيل
الفئة Business Logic Vulnerability
الخطورة 🟠 عالية
درجة CVSS 7.2/10
CWE CWE-841
الملف المتأثر backend/ride/rides/add_ride.php
السطر المتأثر 57-68, 96-144

📌 وصف الثغرة: على الرغم من وجود price_token للتوقيع على الأسعار، إلا أن بعض الحقول الأخرى مثل distance و duration_text لا يتم التحقق منها في الـ token، مما يسمح بالتلاعب ببيانات الرحلة.

🔍 الكود الضعيف:

$distance = filterRequest("distance");
// ... 
$payload[11] = (string) $distance;
$payload[15] = (string) $duration_text;

🎯 تأثير الاستغلال:

  • التلاعب بمسافة الرحلة لعرض سعر أقل
  • التلاعب بمدة الرحلة
  • خداع السائقين ببيانات رحلة مغايرة للواقع

الحل المقترح:

// تضمين distance و duration في الـ price_token أيضاً
if ($tokenData['distance'] != $distance || $tokenData['duration'] != $duration_text) {
    printFailure("Tampered ride data");
    exit;
}

[H-06] — Predictable Token Generation في loginFirstTimeDriver.php

المعلومة التفصيل
الفئة Weak Authentication
الخطورة 🟠 عالية
درجة CVSS 7.0/10
CWE CWE-307, CWE-798
الملف المتأثر backend/loginFirstTimeDriver.php
السطر المتأثر 40-48

📌 وصف الثغرة: يتم استخدام كلمة مرور ثابتة passwordnewpassenger من متغيرات البيئة لكل السائقين الجدد. هذا يسمح لأي شخص يعرف هذه القيمة بتوليد توكن تسجيل صالح.

🔍 الكود الضعيف:

$passwordnewpassenger = getenv('passwordnewpassenger');

if (!password_verify($password, $passwordnewpassenger)) {
    jsonError('Invalid credentials.', 401);
}

🎯 تأثير الاستغلال:

  • إنشاء توكن تسجيل وهمي لأي سائق
  • بدء عملية تسجيل لحسابات متعددة
  • استنزاف موارد الـ OTP والإيميل

الحل المقترح:

// استخدام كلمة مرور فريدة لكل طلب تسجيل (One-Time Token)
$registrationToken = bin2hex(random_bytes(32));
// تخزينها في Redis مع وقت صلاحية وربطها بمعرّف السائق
$redis->setex("reg_token:{$id}", 600, $registrationToken);

// التحقق من الـ token
if (!hash_equals($redis->get("reg_token:{$id}"), $password)) {
    jsonError('Invalid registration token', 401);
}

🟡 الثغرات المتوسطة (Medium)


[M-01] — ملفات Logs بصلاحيات 777

المعلومة التفصيل
الفئة Security Misconfiguration
الخطورة 🟡 متوسطة
درجة CVSS 6.5/10
CWE CWE-276
الملف المتأثر backend/core/helpers.php
السطر المتأثر 158-159

📌 وصف الثغرة: يتم إنشاء مجلد logs بصلاحيات 777 (قابلة للقراءة والكتابة والتنفيذ للجميع). هذا يسمح لأي مستخدم على السيرفر بقراءة وتعديل ملفات الـ logs.

🔍 الكود الضعيف:

@mkdir($logDir, 0777, true);

🎯 تأثير الاستغلال:

  • قراءة معلومات حساسة من الـ logs (User IDs, Tokens, IPs)
  • تعديل الـ logs لإخفاء آثار الاختراق
  • حذف الـ logs

الحل المقترح:

@mkdir($logDir, 0750, true); // Owner: rwx, Group: rx, Others: ---

📚 المراجع:


[M-02] — SQL Injection محتمل في findBestDrivers (Lady Case)

المعلومة التفصيل
الفئة SQL Injection (Potential)
الخطورة 🟡 متوسطة
درجة CVSS 6.0/10
CWE CWE-89
الملف المتأثر backend/functions.php
السطر المتأثر 113-114

📌 وصف الثغرة: في حالة Lady، يتم إدراج $femaleHash مباشرة في الـ SQL. هذه القيمة مشفرة SHA-256 ولكنها لا تزال تُستخدم بدون Prepared Statement.

🔍 الكود الضعيف:

case 'Lady': 
     $femaleHash = 'bQ6yWJ2EVXKZooHdGclvmFiDlZCM8UYeO+ILFjDUvpQ='; 
     $sql .= " AND cr.vehicle_category_id = $CAT_CAR AND d.gender = '$femaleHash' "; 
     break;

الحل المقترح:

case 'Lady': 
     $femaleHash = 'bQ6yWJ2EVXKZooHdGclvmFiDlZCM8UYeO+ILFjDUvpQ='; 
     $sql .= " AND cr.vehicle_category_id = ? AND d.gender = ? ";
     $params[] = $CAT_CAR;
     $params[] = $femaleHash;
     break;

[M-03] — عدم التحقق من SSL في cURL (Man-in-the-Middle)

المعلومة التفصيل
الفئة Insufficient Transport Layer Security
الخطورة 🟡 متوسطة
درجة CVSS 5.9/10
CWE CWE-295
الملف المتأثر backend/functions.php
السطر المتأثر 33-42, 51-61, 170-180, 193-210, 232-252, 342-354

📌 وصف الثغرة: جميع استدعاءات cURL الداخلية إلى http://188.68.36.205:2021 لا تستخدم SSL. هذا يسمح لأي شخص في نفس الشبكة باعتراض الاتصالات.

الحل المقترح:

// استخدام HTTPS بدلاً من HTTP
$url = "https://188.68.36.205:2021"; 

// مع التحقق من SSL certificate
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

[M-04] — عدم وجود فحص للـ Token Expiry في loginJwtDriver.php

المعلومة التفصيل
الفئة Business Logic
الخطورة 🟡 متوسطة
درجة CVSS 5.5/10
CWE CWE-613
الملف المتأثر backend/loginJwtDriver.php
السطر المتأثر 63-68

📌 وصف الثغرة: عند فك تشفير decPhone و decNat، إذا فشلت عملية فك التشفير لا يتم تسجيل خطأ مناسب ولا يتم التحقق من وقت صلاحية بيانات الجلسة.

الحل المقترح:

if (empty($decPhone) || empty($decNat)) {
    securityLog("LoginDriver failed: decryption returned null", [
        'driver_id' => $driver['id'],
        'phone_len' => strlen($driver['phone'] ?? 0),
        'nat_len' => strlen($driver['national_number'] ?? 0)
    ]);
    unauthorizedDriver();
}

🟢 الثغرات المنخفضة (Low)


[L-01] — الـ Headers الأمنية غير كافية

المعلومة التفصيل
الفئة Security Misconfiguration
الخطورة 🟢 منخفضة
درجة CVSS 3.5/10
CWE CWE-693
الملف المتأثر backend/core/bootstrap.php
السطر المتأثر 29-36

📌 وصف الثغرة: بعض الـ Security Headers الأساسية مفقودة أو غير كافية:

  • Content-Security-Policy غير موجود
  • Referrer-Policy غير موجود
  • Permissions-Policy غير موجود
  • X-XSS-Protection غير موجود (للمتصفحات القديمة)

الحل المقترح:

header("Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none'");
header("Referrer-Policy: strict-origin-when-cross-origin");
header("Permissions-Policy: geolocation=(), microphone=(), camera=()");
header("X-XSS-Protection: 1; mode=block");

[L-02] — Email Header Injection في helpers.php

المعلومة التفصيل
الفئة Email Header Injection
الخطورة 🟢 منخفضة
درجة CVSS 3.1/10
CWE CWE-93
الملف المتأثر backend/core/helpers.php
السطر المتأثر 77-81

🔍 الكود الضعيف:

function sendEmail(string $from, string $to, string $title, string $body): void
{
    $header = "From: $from\nCC: $from";
    mail($to, $title, $body, $header);
}

الحل المقترح:

function sendEmail(string $from, string $to, string $title, string $body): void
{
    // تعقيم المدخلات لمنع injection
    $from = str_replace(["\r", "\n", "\r\n"], '', $from);
    $to = str_replace(["\r", "\n", "\r\n"], '', $to);
    $title = str_replace(["\r", "\n", "\r\n"], '', $title);
    
    $header = "From: $from\r\n";
    $header .= "Reply-To: $from\r\n";
    $header .= "MIME-Version: 1.0\r\n";
    $header .= "Content-Type: text/html; charset=UTF-8\r\n";
    
    mail($to, $title, $body, $header);
}

📊 جدول ملخص الثغرات

# الثغرة الملف الخطورة CVSS
C-01 SQL Injection في findBestDrivers functions.php:98-128 🔴 حرجة 9.8
C-02 Hardcoded Secrets Paths متعدد 🔴 حرجة 9.3
C-03 File Upload بدون Auth upload_audio.php 🔴 حرجة 9.0
C-04 Debug Mode مفعل bootstrap.php:11 🔴 حرجة 8.6
C-05 IV ثابت في AES-CBC encrypt_decrypt.php 🔴 حرجة 8.0
H-01 SSRF functions.php 🟠 عالية 7.5
H-02 HMAC Debug Disclosure JwtService.php:268 🟠 عالية 7.5
H-03 CORS Misconfiguration loginAdmin.php:9 🟠 عالية 7.3
H-04 Weak Encryption Flutter encrypt_decrypt.dart 🟠 عالية 7.4
H-05 Business Logic Pricing add_ride.php 🟠 عالية 7.2
H-06 Predictable Reg Token loginFirstTimeDriver.php 🟠 عالية 7.0
M-01 Logs Permissions 777 helpers.php:158 🟡 متوسطة 6.5
M-02 SQL Injection (Lady case) functions.php:114 🟡 متوسطة 6.0
M-03 No SSL Verification functions.php 🟡 متوسطة 5.9
M-04 No Token Expiry Check loginJwtDriver.php 🟡 متوسطة 5.5
L-01 Missing Security Headers bootstrap.php 🟢 منخفضة 3.5
L-02 Email Header Injection helpers.php:77 🟢 منخفضة 3.1

🎯 خارطة طريق الإصلاح (Remediation Roadmap)

المرحلة الأولى: فورية (خلال 24-48 ساعة)

  • C-01: إصلاح SQL Injection في findBestDrivers باستخدام Prepared Statements
  • C-02: نقل جميع المفاتيح إلى متغيرات البيئة فقط وإزالة الـ file_get_contents من الكود
  • C-03: إضافة JWT Authentication إلى upload_audio.php وتعقيم اسم الملف
  • C-04: تعطيل display_errors في الإنتاج

المرحلة الثانية: قصيرة المدى (خلال أسبوع)

  • C-05: الترحيل الكامل إلى AES-256-GCM والتأكد من عدم استخدام IV ثابت
  • H-01: إضافة allowlist لعناوين URL في cURL
  • H-02: إزالة معلومات الـ Debug من استجابات الـ API
  • H-03: تقييد CORS للدومينات المسموحة فقط

المرحلة الثالثة: متوسطة المدى (خلال شهر)

  • H-04: تحديث Flutter Encryption لاستخدام GCM مع IV عشوائي
  • H-05: تضمين جميع حقول الرحلة في الـ price_token
  • H-06: تطبيق One-Time Registration Tokens
  • M-01: تصحيح صلاحيات مجلد الـ logs

المرحلة الرابعة: استراتيجية (شهر - 3 أشهر)

  • M-02: تحويل جميع استعلامات SQL إلى Prepared Statements
  • M-03: تفعيل SSL Verification في جميع اتصالات cURL
  • M-04: إضافة Logging مناسب لجميع حالات الفشل
  • L-01 + L-02: إضافة Security Headers وتأمين دالة الإيميل

🏆 نقاط القوة والنقاط الإيجابية

على الرغم من النتيجة المنخفضة، هناك بعض الممارسات الجيدة في الكود:

  1. استخدام Prepared Statements في معظم استعلامات SQL (عدا الـ findBestDrivers)
  2. وجود Rate Limiting عبر Redis
  3. JWT مع JTI و Blacklist لدعم إلغاء التوكنات
  4. استخدام hash_equals لمقارنة آمنة (Timing Attack Safe)
  5. فصل قواعد البيانات (Main, Ride, Tracking) لتقليل الضرر
  6. تطبيق فحص بصمة الجهاز (Fingerprint) لمنع سرقة الجلسات
  7. استخدام random_bytes لتوليد قيم عشوائية آمنة
  8. التحقق من MIME type الحقيقي في رفع الصور عبر finfo

🔚 الخلاصة

درجة الأمان الإجمالية: 2.5/10 🔴

النظام يحتوي على ثغرات حرجة تتطلب تدخلاً فورياً. الخطر الأكبر يكمن في:

  1. إمكانية حقن SQL والوصول لقاعدة البيانات
  2. وجود المفاتيح في مسارات معروفة داخل الكود
  3. إمكانية رفع ملفات خبيثة بدون مصادقة
  4. استخدام IV ثابت في التشفير

التوصية الفورية: وقف أي deploy جديد حتى يتم إصلاح الثغرات الحرجة في المرحلة الأولى.