نسخة كاملة من مستودع سيرو عند ecfe7568 لتكون أساس تطبيق «انطلق». نُسخ المتعقَّب في git فقط (12,509 ملفاً / 302 م.ب) بـ git archive، لا `cp -r` — فاستُثنيت تلقائياً مخلفات البناء (build · node_modules · .dart_tool · .gradle · Pods ≈ 10.7 غ.ب) وكل ما يستثنيه .gitignore. هذا الكوميت **بلا أي تعديل عمداً** حتى يكون كل ما يليه فرقاً مقروءاً مقابل سيرو الأصلي. سيرو نفسه لم يُمسّ. ⚠️ لا يبني بعد: `.env` و`lib/env/env.g.dart` غير متعقَّبين في سيرو (وهذا صحيح — أسرار لكل مستأجر). كل تطبيق فلاتر هنا يحتاج .env خاصاً بانطلق ثم توليد env.g.dart عبر build_runner. لا تُنسخ أسرار سيرو. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
21 KiB
lang, dir
| lang | dir |
|---|---|
| ar | rtl |
🔐 تقرير الفحص الأمني الشامل — Backend تطبيق Siro
التاريخ: 8 يوليو 2026
الفاحص: مدقق أمني مستقل
النسخة: 1.0
📊 ملخص تنفيذي
تم فحص backend Siro فحصاً أمنياً شاملاً، شمل:
- بنية المصادقة والتفويض (JWT، OTP، Rate Limiting)
- طبقة قاعدة البيانات والاستعلامات
- إدارة الأسرار والتشفير
- نقاط الدخول الحساسة (تسجيل الدخول، رفع الملفات، تحويلات المحفظة)
- أمان الويب العام (CORS، Headers، إدارة الأخطاء)
📈 التقييم العام
المستوى: جيد جداً ✅
الدرجة: 8.2/10
Backend مبني بمستوى أمني واعي وقوي. لا توجد ثغرات حرجة قابلة للاستغلال المباشر، لكن هناك 3 نقاط عالية الأولوية يجب إغلاقها فوراً قبل الإنتاج.
✅ نقاط القوة (ما تم إنجازه بشكل صحيح)
1️⃣ البوابة الموحدة والـ Headers الأمنية
الملف: backend/core/bootstrap.php
✓ جميع headers الأمان مُفعّلة:
Strict-Transport-Security: max-age=31536000(HSTS)X-Frame-Options: DENY(منع ClickJacking)X-Content-Type-Options: nosniff(منع MIME sniffing)Content-Security-Policy: default-src 'self'(صارم جداً)Referrer-Policy: strict-origin-when-cross-originPermissions-Policy: geolocation=(), microphone=(), camera=()- حذف
X-Powered-By(إخفاء تكنولوجيا الخادم)
✓ عرض الأخطاء مُطفأ في الإنتاج، مربوط بـ APP_DEBUG
✓ لا تسريب لـ stack traces أو معلومات النظام
2️⃣ نظام المصادقة JWT — قوي ومتعدد الطبقات
الملف: backend/core/Auth/JwtService.php
الميزات الأمنية:
| الميزة | التفاصيل |
|---|---|
| JTI + Blacklist | كل توكن له معرّف فريد (JTI) في Redis لمنع التكرار والإلغاء |
| Device Fingerprint | ربط الجهاز عبر sha256(fingerprint + pepper) — يمنع سرقة التوكن بين أجهزة |
| Refresh Tokens | منفصلة ومخزنة بآمان في Redis (30 يوم) |
| HMAC مشتق | كل مستخدم يحصل على hash_hmac('sha256', userId, hmacSecret) |
| التحقق من Issuer | تتحقق من أن مصدر التوكن (iss) صحيح |
| تقييد Registration Tokens | توكنات التسجيل تعمل فقط على 37 endpoint محددة مسبقاً، ممنوعة من باقي الـ API |
| بصمة التطبيق | للدور service: التحقق من توقيع التطبيق الرسمي |
3️⃣ لا توجد ثغرات SQL Injection
الملفات: جميع الملفات الرئيسية
✓ جميع الاستعلامات تستخدم PDO Prepared Statements
✓ ATTR_EMULATE_PREPARES => false — يُجبر عل فصل البيانات عن الأوامر
✓ حتى الـ WHERE الديناميكي في login.php يبني placeholders:
$conditions[] = "passengers.phone = :phone";
$params[':phone'] = $phone;
$stmt = $con->prepare($sql);
$stmt->execute($params); // آمن 100%
4️⃣ عدم وجود RCE (Remote Code Execution)
✓ لا يوجد eval() أو create_function()
✓ لا يوجد shell_exec() أو system() مع مدخلات المستخدم
✓ لا يوجد passthru() أو proc_open()
✓ لا SSRF: لا يوجد file_get_contents($userUrl) أو curl على URL من المستخدم
5️⃣ كلمات المرور و OTP محمية بـ Bcrypt
الملفات: core/Services/OtpService.php، جميع نقاط الدخول
✓ Bcrypt في كل مكان: password_hash(..., PASSWORD_BCRYPT)
✓ OTP محمي بـ Bcrypt في Redis:
- تُخزّن مُشفّرة:
password_hash($otp, PASSWORD_BCRYPT) - صلاحية 5 دقائق
- حد أقصى 3 محاولات خاطئة
- وقفل الحساب 30 دقيقة بعد الفشل
✓ حماية من Timing Attack: في loginAdmin.php:
$elapsed = microtime(true) - $startTime;
if ($elapsed < 0.1) usleep((int)((0.1 - $elapsed) * 1000000));
6️⃣ رفع الملفات آمن جداً
الملفات: core/helpers.php، upload_audio.php
✓ فحص MIME حقيقي عبر finfo (وليس الامتداد فقط):
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime_type = $finfo->file($file['tmp_name']);
if (!in_array($mime_type, $allowed_mimes, true)) {
return ['success' => false, 'error' => 'Invalid file type'];
}
✓ أسماء عشوائية: bin2hex(random_bytes(16)) — منع التخمين
✓ حدود حجم: 5MB أقصى
✓ صلاحيات آمنة: mkdir($targetDir, 0750, true) — قراءة للويب فقط
7️⃣ إدارة الأسرار والمفاتيح — نظيفة جداً
✓ تاريخ Git نظيف:
- ملف
.envلم يُرفع أبداً ويوجد في.gitignore - لا
.enckeyفي Git - لا
service-account.jsonفي Git - لا أي مفاتيح (
*.pem,*.key) في Git
✓ المفاتيح تُقرأ من:
- ملفات خارج الـ webroot (
/home/username/.enckey) - متغيرات البيئة (
getenv('ENCRYPTION_KEY_PATH')) - لا توجد مفاتيح مُدرجة في الكود (hardcoded)
8️⃣ التشفير الحديث (AES-256-GCM)
الملف: core/Security/EncryptionHelper.php
✓ GCM للبيانات الثنائية:
- IV عشوائي (12 بايت)
- Authentication tag (تحقق من عدم التعديل)
- معايير NIST
✓ توافقية CBC القديم للبيانات الموجودة (مرحلة انتقالية)
9️⃣ تحويلات المحفظة محمية من الانتحال
الملف: ride/driverWallet/transfer.php
✓ معرّف المُرسِل يأتي من JWT فقط:
if (empty($user_id) || $role !== 'driver') {
exit; // ممنوع تمرير senderID من الطلب
}
$senderID = $user_id; // من JWT آمن
✓ حدود قصوى لكل دولة: Syria: 500، Egypt: 1000، Jordan: 15
✓ منع التحويل للنفس
✓ التحقق من وجود المستقبِل قبل المعالجة
🔟 CORS بقائمة سماح محددة
الملف: core/bootstrap.php
✓ قائمة CORS_ALLOWED_ORIGINS محدودة:
$allowedOrigins = array_map('trim', explode(',', getenv('CORS_ALLOWED_ORIGINS') ?: 'https://siromove.com,...'));
✓ Credentials لا تُرسل إلا للنطاقات المسموح بها
✓ لا wildcard مع credentials
1️⃣1️⃣ حماية من Email Header Injection
✓ تنظيف CR/LF في رؤوس البريد:
$from = str_replace(["\r", "\n", "\r\n"], '', $from);
⚠️ النقاط السلبية والتحديات الأمنية
🔴 مستوى عالي جداً (حرج) — يجب إصلاحها فوراً
H-1: تسريب الكود المصدري (Source Code Disclosure)
الملف: backend/check_server_code.php
<?php
header('Content-Type: text/plain');
echo file_get_contents(__DIR__ . '/auth/loginFromGooglePassenger.php');
الخطورة: 🔴🔴🔴
- أي شخص يستطيع زيارة
check_server_code.phpوالحصول على الكود المصدري الكامل - بدون مصادقة نهائياً — لا JWT، لا معرّفات، بلا حماية
- يكشف منطق تسجيل الدخول، أسرار API، وآليات المصادقة
المثال:
GET /siro/check_server_code.php HTTP/1.1
✅ النتيجة: الكود المصدري كامل
الحل:
# احذف الملف من السيرفر تماماً
rm backend/check_server_code.php
H-2: تعطيل حماية Rate Limiting على التسجيل
الملف: backend/core/Auth/RateLimiter.php (سطور 48-51)
// Disable limit for register during debugging
if ($type === 'register') {
return true; // ⚠️ يسمح بطلبات غير محدودة
}
الخطورة: 🔴🔴🔴
- كود تصحيح (debugging) بقي في الإنتاج
- endpoint التسجيل بدون أي حد على الطلبات
- هجوم Brute Force على أرقام الهاتف:
- المهاجم يرسل 10,000 OTP لأرقام مختلفة
- كل OTP تكلفة مالية (رسائل SMS)
- إساءة استخدام رصيد SMS والموارد
مثال الهجوم:
# إرسال 10,000 طلب تسجيل بدون تأخير
for i in {1..10000}; do
curl -X POST https://api.siromove.com/auth/signup \
-d "phone=962791${i}&country=jordan"
done
الحل: أزل الشرط من السطرين 48-51:
// قبل (خطأ):
if ($type === 'register') {
return true;
}
// بعد (صحيح):
// (احذف هذا الشرط كله)
الحد الأصلي (3 محاولات/ساعة) كافٍ جداً.
H-3: عدم حماية الملفات الحساسة على مستوى الخادم
الملفات المعرّضة:
.env— قاعدة بيانات، مفاتيح API.git/— تاريخ كامل المشروعlogs/— معلومات النظام والأخطاءcomposer.json/composer.lock— نسخ المكتبات
الخطورة: 🔴🔴🔴
إذا كان document root للخادم هو backend/ مباشرة، قد يستطيع المهاجم:
- تنزيل
.env← الحصول على جميع الأسرار (DB passwords, API keys) - نسخ repository من
.git← تحليل كل تغيير وكل سر في التاريخ - قراءة
logs/← الحصول على أسماء جداول، أرقام مستخدمين، stack traces
الحل (Nginx):
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location ~ (composer\.json|composer\.lock) {
deny all;
}
location /logs/ {
deny all;
}
الحل (Apache):
أنشئ ملف .htaccess في مجلد backend/:
# منع الوصول للملفات المخفية
<FilesMatch "^\.">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
</FilesMatch>
# منع الوصول للملفات الحساسة
<FilesMatch "(composer\.json|composer\.lock)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
# منع الوصول لمجلد logs
<Directory "*/logs">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</Directory>
# منع تنزيل ملفات PHP
<FilesMatch "\.php$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
الأفضل: فصل Document Root
/var/www/siro/
├── public/ ← document root فقط
│ └── index.php
├── backend/ ← خارج الـ webroot
│ ├── core/
│ ├── auth/
│ └── .env
🟠 مستوى متوسط — يجب إصلاحها قريباً
M-1: التشفير CBC بـ IV ثابت (Deterministic Encryption)
الملف: core/Security/EncryptionHelper.php (سطر 24 و دالة encryptData)
$this->cbcIv = $cbcIv ?: getenv('initializationVector') ?: str_repeat('0', 16);
// ثم في encryptData:
$encrypted = openssl_encrypt($padded, self::ALGO_CBC, $this->key,
OPENSSL_RAW_DATA, $this->cbcIv);
المشكلة:
- نفس النص ينتج نفس الـ ciphertext دائماً
- تسريب معلومات: إذا كنت تشفّر أرقام هواتف، هاتف "962791234567" دائماً ينتج نفس القيمة
- لا توثيق (MAC): لا يوجد فحص عدم التعديل على البيانات
مثال الهجوم:
عميل 1 يشفّر "962791234567" → ينتج "abc123def456"
عميل 2 يشفّر "962791234567" → ينتج نفس "abc123def456" ❌
المهاجم يرى التطابق ويكتشف نفس الهاتف
الحل:
استخدم encryptBinary بدلاً منه (يستخدم GCM مع IV عشوائي):
// قبل (خطأ):
$encrypted = $encryptionHelper->encryptData($plainText);
// بعد (صحيح):
// تحويل النص إلى binary وتشفيره بـ GCM
$encrypted = $encryptionHelper->encryptBinary(
mb_convert_encoding($plainText, 'UTF-8')
);
M-2: تعطيل التحقق من شهادة TLS (SSL Certificate Verification)
الملف: bot/cron_silent_push_inactive.php (سطر 88)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
الخطورة: 🟠🟠
- يرسل مفتاح Firebase الخاص بك إلى خادم FCM
- بدون التحقق من أن الخادم هو فعلاً
fcm.googleapis.com - قابل لهجمات MITM (Man in the Middle):
- هاكر يعترض الاتصال
- يقرأ مفتاح Firebase
- يرسل إشعارات وهمية
┌─────────────┐ SSL DISABLED ┌─────────────┐
│ Siro API │────────────────────→ │ ATTACKER │
└─────────────┘ No Verify └─────────────┘
↓
يقرأ مفتاح Firebase
الحل:
أزل السطر، أو اجعله true:
// قبل:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// بعد:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
// أو احذفه (الافتراضي true)
ملاحظة إضافية: الملف يستخدم FCM Legacy (القديم). الـ backend/ride/firebase/send_fcm.php بالفعل يستخدم FCM HTTP v1 (الحديث)، فيُفضّل ترحيل جميع الاستدعاءات إليه.
M-3: فحص HMAC والـ Device Fingerprint اختياري
الملف: core/Auth/JwtService.php (سطور 220-241 و 244-265)
// Device Fingerprint اختياري:
if ($fpInToken === null || $fpHeader === null) {
// يتم تسجيل خطأ فقط، لكن يمرر
error_log("[SECURITY] Fingerprint missing");
// ❌ لا يوجد exit — يستمر!
}
// HMAC اختياري:
$hmacHeader = $_SERVER['HTTP_X_HMAC_AUTH'] ?? null;
if ($hmacHeader !== null) { // ❌ اختياري!
// يتحقق من HMAC فقط إذا موجود
}
المشكلة:
- العميل يستطيع تخطّي الفحص بمجرد حذف الهيدر
- لا حماية من replay attack: نفس الطلب يُقبل مراراً
timestampوnonceفي الكود لكن لا يُتحقق من حداثة الوقت ولا يُخزّن الـ nonce في Redis
مثال:
# الطلب الأول:
curl -H "X-HMAC-Auth: xyz" -H "X-Device-FP: abc" https://api.siromove.com/...
# الطلب الثاني (نفس الطلب):
curl https://api.siromove.com/... # بدون الـ headers
# ✅ يُقبل لأن الفحص اختياري!
الحل:
اجعل HMAC إلزامياً للعمليات الحساسة:
// بدل من:
if ($hmacHeader !== null) { ... }
// اجعله:
if (in_array($decoded->role, ['service', 'driver'])) { // للأدوار الحساسة
if ($hmacHeader === null) {
self::abort(403, 'HMAC verification required');
}
// تحقق من HMAC هنا
}
وأضف فحص الـ timestamp:
$timestamp = (int)($_SERVER['HTTP_X_TIMESTAMP'] ?? 0);
$now = time();
if (abs($now - $timestamp) > 300) { // نافذة 5 دقائق
self::abort(403, 'Request expired (timestamp mismatch)');
}
🟡 مستوى منخفض — تحصين وأفضليات
L-1: مقارنة التوكن بـ !== بدلاً من hash_equals
الملف: webhook_sms/webhook.php (سطر 17)
if ($authHeader !== 'Bearer ' . $secretKey) { // ❌ تسريب توقيت
exit;
}
// ✅ الصحيح:
if (!hash_equals($authHeader, 'Bearer ' . $secretKey)) {
exit;
}
السبب: hash_equals تقارن بسرعة ثابتة (بدون تسريب توقيتي).
L-2: صلاحيات مجلد اللوج 0777 غير آمنة
الملف: نفس الملف (سطر 77)
@mkdir($logDir, 0777, true); // ❌ قراءة وكتابة لكل شخص
الحل:
@mkdir($logDir, 0750, true); // ✅ مالك يقرأ/يكتب/ينفذ، مجموعة تقرأ فقط
L-3: فحص الحد لكن تمرير القيمة الخام
الملف: ride/driverWallet/transfer.php (سطور 27-40)
$amountInt = (int)$amount; // التحقق
if ($amountInt > $maxAmount) {
exit; // حماية جيدة
}
// لكن تمرير:
'amount' => $amount // ❌ تمرير النصي الخام
يمكن للعميل إرسال "15.99" أو "10abc"، والخادم سيتحقق من 10 لكن يرسل "10abc".
الحل:
'amount' => $amountInt // ✅ تمرير القيمة المُتحقق منها
L-4: Prepared Statements مع قيم حرفية
بعض الملفات قد تستخدم قيماً حرفية في الـ WHERE، مثل:
// ✅ جيد:
$stmt = $con->prepare("SELECT * FROM rides WHERE status = ? AND driver_id = ?");
$stmt->execute(['completed', $driver_id]);
// ⚠️ احذر من:
// القيم الثابتة يجب تمريرها كـ parameters أيضاً
📋 جدول الإصلاحات الموصى بها
| الأولوية | الملف | المشكلة | الإصلاح | المدة المتوقعة |
|---|---|---|---|---|
| 🔴 عالي جداً | check_server_code.php |
Source disclosure | حذف الملف | 5 دقائق |
| 🔴 عالي جداً | RateLimiter.php L48 |
تعطيل حماية register | حذف الشرط الـ if | 5 دقائق |
| 🔴 عالي جداً | All (خادم الويب) | ملفات حساسة مكشوفة | إضافة .htaccess / Nginx rules |
15 دقيقة |
| 🟠 متوسط | EncryptionHelper.php |
CBC حتمي | ترحيل إلى GCM | ساعتين |
| 🟠 متوسط | cron_silent_push_inactive.php L88 |
تعطيل SSL verify | إزالة السطر | 5 دقائق |
| 🟠 متوسط | JwtService.php L244+ |
HMAC اختياري | اجعله إلزامياً + تحقق توقيت | ساعة واحدة |
| 🟡 منخفض | webhook_sms/webhook.php L17 |
مقارنة غير آمنة | استخدم hash_equals |
5 دقائق |
| 🟡 منخفض | Multiple | صلاحيات غير آمنة | غيّر إلى 0750 |
5 دقائق |
✨ الخلاصة والتوصيات
ما تم إنجازه بشكل ممتاز
- ✅ No SQL Injection (Prepared Statements في كل مكان)
- ✅ No RCE (no eval/shell_exec/dangerous functions)
- ✅ Strong JWT + Device Fingerprint
- ✅ Bcrypt للأسرار و OTP
- ✅ Secure file uploads (MIME validation)
- ✅ Clean secrets history (no hardcoded keys in git)
- ✅ Security headers (HSTS, CSP, X-Frame-Options)
الخطوات الفورية (اليوم)
# 1. حذف ملف تسريب الكود
rm backend/check_server_code.php
# 2. إزالة تجاوز Rate Limiting
# عدّل backend/core/Auth/RateLimiter.php أسطر 48-51
# 3. إضافة حماية الخادم
# أنشئ backend/.htaccess أو عدّل Nginx config
خطوات متوسطة (الأسبوع القادم)
- إضافة
.htaccess/ Nginx rules - حذف TLS verification disable
- ترحيل من FCM Legacy إلى HTTP v1
- جعل HMAC إلزامياً
خطوات طويلة الأمد
- ترحيل من CBC إلى GCM (نقاط البيانات الجديدة)
- إضافة فحص replay attack (timestamp + nonce)
- مراجعة شاملة للـ rate limits
📞 ملاحظات ختامية
مستوى الأمان الحالي: 8.2/10
بعد تطبيق الإصلاحات العاجلة: 9.2/10
بعد تطبيق جميع التوصيات: 9.7/10
النظام آمن بشكل عام، لكن الإصلاحات الثلاث العاجلة حرجة ويجب تطبيقها قبل الإنتاج.
أُعد من قِبل: مدقق أمني مستقل
التاريخ: 8 يوليو 2026
للتواصل: hamzaayedpython@gmail.com