638 lines
21 KiB
Markdown
638 lines
21 KiB
Markdown
---
|
|
lang: ar
|
|
dir: 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-origin`
|
|
- `Permissions-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:
|
|
|
|
```php
|
|
$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`:
|
|
```php
|
|
$elapsed = microtime(true) - $startTime;
|
|
if ($elapsed < 0.1) usleep((int)((0.1 - $elapsed) * 1000000));
|
|
```
|
|
|
|
---
|
|
|
|
### 6️⃣ رفع الملفات آمن جداً
|
|
**الملفات:** `core/helpers.php`، `upload_audio.php`
|
|
|
|
✓ **فحص MIME حقيقي** عبر `finfo` (وليس الامتداد فقط):
|
|
```php
|
|
$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 فقط:**
|
|
```php
|
|
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` محدودة:
|
|
```php
|
|
$allowedOrigins = array_map('trim', explode(',', getenv('CORS_ALLOWED_ORIGINS') ?: 'https://siromove.com,...'));
|
|
```
|
|
|
|
✓ Credentials **لا تُرسل إلا للنطاقات المسموح بها**
|
|
✓ لا wildcard مع credentials
|
|
|
|
---
|
|
|
|
### 1️⃣1️⃣ حماية من Email Header Injection
|
|
✓ تنظيف CR/LF في رؤوس البريد:
|
|
```php
|
|
$from = str_replace(["\r", "\n", "\r\n"], '', $from);
|
|
```
|
|
|
|
---
|
|
|
|
## ⚠️ النقاط السلبية والتحديات الأمنية
|
|
|
|
---
|
|
|
|
### 🔴 مستوى عالي جداً (حرج) — يجب إصلاحها فوراً
|
|
|
|
#### **H-1: تسريب الكود المصدري (Source Code Disclosure)**
|
|
|
|
**الملف:** `backend/check_server_code.php`
|
|
|
|
```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
|
|
```
|
|
✅ النتيجة: الكود المصدري كامل
|
|
|
|
**الحل:**
|
|
```bash
|
|
# احذف الملف من السيرفر تماماً
|
|
rm backend/check_server_code.php
|
|
```
|
|
|
|
---
|
|
|
|
#### **H-2: تعطيل حماية Rate Limiting على التسجيل**
|
|
|
|
**الملف:** `backend/core/Auth/RateLimiter.php` (سطور 48-51)
|
|
|
|
```php
|
|
// Disable limit for register during debugging
|
|
if ($type === 'register') {
|
|
return true; // ⚠️ يسمح بطلبات غير محدودة
|
|
}
|
|
```
|
|
|
|
**الخطورة:** 🔴🔴🔴
|
|
- كود تصحيح (debugging) **بقي في الإنتاج**
|
|
- endpoint التسجيل **بدون أي حد** على الطلبات
|
|
- هجوم **Brute Force على أرقام الهاتف:**
|
|
- المهاجم يرسل 10,000 OTP لأرقام مختلفة
|
|
- كل OTP تكلفة مالية (رسائل SMS)
|
|
- إساءة استخدام رصيد SMS والموارد
|
|
|
|
**مثال الهجوم:**
|
|
```bash
|
|
# إرسال 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:
|
|
|
|
```php
|
|
// قبل (خطأ):
|
|
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):**
|
|
```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/`:
|
|
```apache
|
|
# منع الوصول للملفات المخفية
|
|
<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`)
|
|
|
|
```php
|
|
$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 عشوائي):
|
|
|
|
```php
|
|
// قبل (خطأ):
|
|
$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)
|
|
|
|
```php
|
|
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`:
|
|
|
|
```php
|
|
// قبل:
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
|
// بعد:
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
|
// أو احذفه (الافتراضي true)
|
|
```
|
|
|
|
**ملاحظة إضافية:**
|
|
الملف يستخدم FCM Legacy (القديم). الـ [backend/ride/firebase/send_fcm.php](send_fcm.php) بالفعل يستخدم FCM HTTP v1 (الحديث)، فيُفضّل ترحيل جميع الاستدعاءات إليه.
|
|
|
|
---
|
|
|
|
#### **M-3: فحص HMAC والـ Device Fingerprint اختياري**
|
|
|
|
**الملف:** `core/Auth/JwtService.php` (سطور 220-241 و 244-265)
|
|
|
|
```php
|
|
// 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
|
|
|
|
**مثال:**
|
|
```bash
|
|
# الطلب الأول:
|
|
curl -H "X-HMAC-Auth: xyz" -H "X-Device-FP: abc" https://api.siromove.com/...
|
|
|
|
# الطلب الثاني (نفس الطلب):
|
|
curl https://api.siromove.com/... # بدون الـ headers
|
|
# ✅ يُقبل لأن الفحص اختياري!
|
|
```
|
|
|
|
**الحل:**
|
|
|
|
اجعل HMAC إلزامياً للعمليات الحساسة:
|
|
|
|
```php
|
|
// بدل من:
|
|
if ($hmacHeader !== null) { ... }
|
|
|
|
// اجعله:
|
|
if (in_array($decoded->role, ['service', 'driver'])) { // للأدوار الحساسة
|
|
if ($hmacHeader === null) {
|
|
self::abort(403, 'HMAC verification required');
|
|
}
|
|
// تحقق من HMAC هنا
|
|
}
|
|
```
|
|
|
|
وأضف فحص الـ timestamp:
|
|
|
|
```php
|
|
$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)
|
|
|
|
```php
|
|
if ($authHeader !== 'Bearer ' . $secretKey) { // ❌ تسريب توقيت
|
|
exit;
|
|
}
|
|
|
|
// ✅ الصحيح:
|
|
if (!hash_equals($authHeader, 'Bearer ' . $secretKey)) {
|
|
exit;
|
|
}
|
|
```
|
|
|
|
**السبب:** `hash_equals` تقارن بسرعة ثابتة (بدون تسريب توقيتي).
|
|
|
|
---
|
|
|
|
#### **L-2: صلاحيات مجلد اللوج `0777` غير آمنة**
|
|
|
|
**الملف:** نفس الملف (سطر 77)
|
|
|
|
```php
|
|
@mkdir($logDir, 0777, true); // ❌ قراءة وكتابة لكل شخص
|
|
```
|
|
|
|
**الحل:**
|
|
```php
|
|
@mkdir($logDir, 0750, true); // ✅ مالك يقرأ/يكتب/ينفذ، مجموعة تقرأ فقط
|
|
```
|
|
|
|
---
|
|
|
|
#### **L-3: فحص الحد لكن تمرير القيمة الخام**
|
|
|
|
**الملف:** `ride/driverWallet/transfer.php` (سطور 27-40)
|
|
|
|
```php
|
|
$amountInt = (int)$amount; // التحقق
|
|
if ($amountInt > $maxAmount) {
|
|
exit; // حماية جيدة
|
|
}
|
|
|
|
// لكن تمرير:
|
|
'amount' => $amount // ❌ تمرير النصي الخام
|
|
```
|
|
|
|
يمكن للعميل إرسال `"15.99"` أو `"10abc"`، والخادم سيتحقق من `10` لكن يرسل `"10abc"`.
|
|
|
|
**الحل:**
|
|
```php
|
|
'amount' => $amountInt // ✅ تمرير القيمة المُتحقق منها
|
|
```
|
|
|
|
---
|
|
|
|
#### **L-4: Prepared Statements مع قيم حرفية**
|
|
|
|
**بعض الملفات** قد تستخدم قيماً حرفية في الـ WHERE، مثل:
|
|
|
|
```php
|
|
// ✅ جيد:
|
|
$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 دقائق |
|
|
|
|
---
|
|
|
|
## ✨ الخلاصة والتوصيات
|
|
|
|
### ما تم إنجازه بشكل ممتاز
|
|
1. ✅ No SQL Injection (Prepared Statements في كل مكان)
|
|
2. ✅ No RCE (no eval/shell_exec/dangerous functions)
|
|
3. ✅ Strong JWT + Device Fingerprint
|
|
4. ✅ Bcrypt للأسرار و OTP
|
|
5. ✅ Secure file uploads (MIME validation)
|
|
6. ✅ Clean secrets history (no hardcoded keys in git)
|
|
7. ✅ Security headers (HSTS, CSP, X-Frame-Options)
|
|
|
|
### الخطوات الفورية (اليوم)
|
|
```bash
|
|
# 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
|