add the main file structure requirements
This commit is contained in:
@@ -0,0 +1,82 @@
|
|||||||
|
# Ghaymah Security Operations Exam
|
||||||
|
## اختبار عمليات الأمن السيبراني - غيمة
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 👤 معلومات المتقدم
|
||||||
|
|
||||||
|
| البيان | المعلومات |
|
||||||
|
|--------|-----------|
|
||||||
|
| **الاسم** | Ahmed Mohamed Ibrahim |
|
||||||
|
| **قبيلة** | [@ahmedmibrahim](https://qabilah.com/profile/ahmedmibrahim) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 هيكل المشروع
|
||||||
|
|
||||||
|
```
|
||||||
|
ghaymah-exam-ahmedmohamed-SecOps/
|
||||||
|
├── q1-security-audit/
|
||||||
|
│ └── security-checklist.md # قائمة التدقيق الأمني
|
||||||
|
├── q2-attack-simulation/
|
||||||
|
│ ├── incident-response-plan.md # خطة الاستجابة للحوادث
|
||||||
|
│ └── timeline-analysis.md # تحليل الجدول الزمني
|
||||||
|
├── q3-privacy-assessment/
|
||||||
|
│ └── privacy-report.md # تقرير تقييم الخصوصية
|
||||||
|
├── q4-siem-system/
|
||||||
|
│ ├── deployment-guide.md # دليل نشر SIEM
|
||||||
|
│ └── dashboard/
|
||||||
|
│ ├── index.html
|
||||||
|
│ ├── styles.css
|
||||||
|
│ └── app.js
|
||||||
|
├── q5-ransomware-response/
|
||||||
|
│ ├── emergency-plan.md # خطة الطوارئ
|
||||||
|
│ ├── prevention-plan.md # خطة الوقاية
|
||||||
|
│ └── backup-recovery-strategy.md # استراتيجية النسخ الاحتياطي
|
||||||
|
├── common-mortakaz/
|
||||||
|
│ ├── integration-1.md # تكامل Taylor CV مع غيمة
|
||||||
|
│ └── integration-2.md # تكامل Green Framework مع غيمة
|
||||||
|
├── common-qabilah/
|
||||||
|
│ └── qabilah-profile.txt # رابط حساب قبيلة
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 ملخص الأسئلة المُجابة
|
||||||
|
|
||||||
|
| السؤال | الموضوع | الحالة |
|
||||||
|
|--------|---------|--------|
|
||||||
|
| Q1 | Security Audit Checklist | ✅ مكتمل |
|
||||||
|
| Q2 | Attack Simulation & Incident Response | ✅ مكتمل |
|
||||||
|
| Q3 | Privacy Assessment (mithal.space) | ✅ مكتمل |
|
||||||
|
| Q4 | SIEM System with Block Storage | ✅ مكتمل |
|
||||||
|
| Q5 | Ransomware Response Plan | ✅ مكتمل |
|
||||||
|
| Q6 | Integration Proposals (mortakaz.com) | ✅ مكتمل |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 روابط مهمة
|
||||||
|
|
||||||
|
- **غيمة Cloud**: [ghaymah.systems](https://ghaymah.systems)
|
||||||
|
- **مثال Search**: [mithal.space](https://mithal.space)
|
||||||
|
- **مرتكز**: [mortakaz.com](https://www.mortakaz.com)
|
||||||
|
- **قبيلة**: [qabilah.com](https://qabilah.com)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛡️ المهارات المُظهرة
|
||||||
|
|
||||||
|
- تدقيق أمني شامل
|
||||||
|
- تحليل الحوادث الأمنية
|
||||||
|
- تقييم الخصوصية
|
||||||
|
- تصميم أنظمة SIEM
|
||||||
|
- خطط الاستجابة للطوارئ
|
||||||
|
- استراتيجيات النسخ الاحتياطي (3-2-1)
|
||||||
|
- اقتراحات التكامل التقني
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 التواصل
|
||||||
|
|
||||||
|
تابعني على قبيلة: **[@ahmedmibrahim](https://qabilah.com/profile/ahmedmibrahim)**
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# اقتراح التكامل الأول: تايلور سي في (Taylor CV)
|
||||||
|
## Integration Proposal: Taylor CV + Ghaymah Cloud
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## وصف المنتج
|
||||||
|
|
||||||
|
منصة ذكاء اصطناعي تنشئ سيرة ذاتية ورسالة تحفيزية مخصصة لكل وظيفة، وتحضر للمقابلات، وتقدم خطط تعلم يومية، وتدعم لغات متعددة.
|
||||||
|
|
||||||
|
**الرابط:** [Taylor CV على مرتكز](https://www.mortakaz.com/projects/6a60ad7e3d576288c1011ff2)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## كيف يتكامل مع ghaymah.systems
|
||||||
|
|
||||||
|
| جانب التكامل | التفاصيل |
|
||||||
|
|--------------|----------|
|
||||||
|
| **الاستضافة** | استضافة التطبيق على Ghaymah Cloud باستخدام Container Services |
|
||||||
|
| **قاعدة البيانات** | استخدام PostgreSQL المُدار من غيمة لتخزين بيانات المستخدمين والسير الذاتية |
|
||||||
|
| **التخزين** | Block Storage لحفظ ملفات PDF المُولّدة والقوالب |
|
||||||
|
| **الأمان** | تفعيل SSL التلقائي وMFA لحماية بيانات المستخدمين الحساسة |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## التكامل التقني
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml for Taylor CV on Ghaymah
|
||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
taylor-cv-app:
|
||||||
|
image: taylor-cv:latest
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=postgresql://user:pass@ghaymah-postgres:5432/taylorcv
|
||||||
|
- STORAGE_ENDPOINT=https://storage.ghaymah.systems
|
||||||
|
- AI_API_KEY=${OPENAI_KEY}
|
||||||
|
deploy:
|
||||||
|
replicas: 2
|
||||||
|
|
||||||
|
ghaymah-postgres:
|
||||||
|
image: postgres:15
|
||||||
|
volumes:
|
||||||
|
- ghaymah-block-storage:/var/lib/postgresql/data
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## القيمة المضافة للمستخدم النهائي
|
||||||
|
|
||||||
|
| الفائدة | الوصف |
|
||||||
|
|---------|-------|
|
||||||
|
| **سرعة الأداء** | خوادم غيمة في السعودية = زمن استجابة أقل للمستخدمين العرب |
|
||||||
|
| **أمان البيانات** | البيانات تبقى في المنطقة العربية (Data Sovereignty) |
|
||||||
|
| **تكلفة أقل** | أسعار غيمة التنافسية تقلل تكلفة التشغيل |
|
||||||
|
| **دعم عربي** | دعم فني باللغة العربية |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## رسم بسيط للتكامل (Architecture Sketch)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ Ghaymah Cloud │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||||
|
│ │ Users │───▶│ Taylor CV │───▶│ PostgreSQL │ │
|
||||||
|
│ │ (العرب) │ │ Container │ │ (Managed) │ │
|
||||||
|
│ └──────────────┘ └──────┬───────┘ └──────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌──────────────┐ │
|
||||||
|
│ │ Block Storage│ │
|
||||||
|
│ │ (PDF Files) │ │
|
||||||
|
│ └──────────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## التحديات التقنية والتجارية المحتملة
|
||||||
|
|
||||||
|
| التحدي | الحل المقترح |
|
||||||
|
|--------|--------------|
|
||||||
|
| **تكامل AI APIs** | استخدام API Gateway من غيمة لإدارة الاتصال مع OpenAI |
|
||||||
|
| **حجم التخزين** | خطة تسعير مرنة حسب الاستخدام من غيمة |
|
||||||
|
| **التوسع** | Auto-scaling مع Container Services |
|
||||||
|
| **الامتثال** | غيمة متوافقة مع متطلبات حماية البيانات السعودية |
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
# اقتراح التكامل الثاني: جرين (Green PHP Framework)
|
||||||
|
## Integration Proposal: Green Framework + Ghaymah Cloud + mithal.space
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## وصف المنتج
|
||||||
|
|
||||||
|
إطار عمل PHP حديث وخفيف، يسهل بناء تطبيقات الويب وواجهات برمجة التطبيقات بوضوح وتنظيم وقابلية للتوسع.
|
||||||
|
|
||||||
|
**الرابط:** [Green على مرتكز](https://www.mortakaz.com/projects/6a66386b64ffff87848cfc37)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## كيف يتكامل مع ghaymah.systems
|
||||||
|
|
||||||
|
| جانب التكامل | التفاصيل |
|
||||||
|
|--------------|----------|
|
||||||
|
| **Template جاهز** | إنشاء قالب Green جاهز للنشر بنقرة واحدة على غيمة |
|
||||||
|
| **CI/CD** | تكامل مع GitHub Actions للنشر التلقائي |
|
||||||
|
| **قاعدة البيانات** | دعم مباشر لـ PostgreSQL من غيمة في إعدادات Framework |
|
||||||
|
| **التوثيق** | توثيق خاص بالنشر على غيمة |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## التكامل التقني مع غيمة
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
// config/database.php - Green Framework + Ghaymah
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default' => 'ghaymah_postgres',
|
||||||
|
|
||||||
|
'connections' => [
|
||||||
|
'ghaymah_postgres' => [
|
||||||
|
'driver' => 'pgsql',
|
||||||
|
'host' => env('GHAYMAH_DB_HOST', 'db.ghaymah.systems'),
|
||||||
|
'port' => env('GHAYMAH_DB_PORT', '5432'),
|
||||||
|
'database' => env('GHAYMAH_DB_NAME', 'myapp'),
|
||||||
|
'username' => env('GHAYMAH_DB_USER'),
|
||||||
|
'password' => env('GHAYMAH_DB_PASS'),
|
||||||
|
'ssl_mode' => 'require',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# نشر تطبيق Green على غيمة
|
||||||
|
ghaymah app create my-green-app \
|
||||||
|
--template green-php \
|
||||||
|
--database postgres \
|
||||||
|
--region me-riyadh-1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## كيف يتكامل مع mithal.space
|
||||||
|
|
||||||
|
| جانب التكامل | التفاصيل |
|
||||||
|
|--------------|----------|
|
||||||
|
| **Search API** | إضافة package للبحث عبر mithal.space API |
|
||||||
|
| **الخصوصية** | بديل لـ Google Search في التطبيقات التي تحترم الخصوصية |
|
||||||
|
| **دعم العربية** | نتائج بحث محسّنة للمحتوى العربي |
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
// packages/mithal-search/src/MithalSearch.php
|
||||||
|
|
||||||
|
namespace Green\MithalSearch;
|
||||||
|
|
||||||
|
class MithalSearch
|
||||||
|
{
|
||||||
|
private string $baseUrl = 'https://mithal.space/api/search';
|
||||||
|
|
||||||
|
public function search(string $query, array $options = []): array
|
||||||
|
{
|
||||||
|
// بحث يحترم الخصوصية - لا تتبع
|
||||||
|
return $this->request([
|
||||||
|
'q' => $query,
|
||||||
|
'lang' => $options['lang'] ?? 'ar',
|
||||||
|
'safe' => $options['safe'] ?? true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## القيمة المضافة للمستخدم النهائي
|
||||||
|
|
||||||
|
| الفائدة | الوصف |
|
||||||
|
|---------|-------|
|
||||||
|
| **سهولة النشر** | من الكود إلى Production في دقائق |
|
||||||
|
| **بحث عربي** | نتائج بحث أفضل للمحتوى العربي عبر mithal |
|
||||||
|
| **خصوصية** | لا تتبع للمستخدمين |
|
||||||
|
| **تكلفة** | استضافة بأسعار تنافسية |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## رسم بسيط للتكامل (Architecture Sketch)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ Green Framework App │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────┐ ┌──────────────┐ │
|
||||||
|
│ │ Green │────────▶│ Ghaymah │ │
|
||||||
|
│ │ PHP App │ │ Cloud │ │
|
||||||
|
│ └──────┬───────┘ └──────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ │ Search API │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌──────────────┐ │
|
||||||
|
│ │ mithal.space│ │
|
||||||
|
│ │ (بحث عربي) │ │
|
||||||
|
│ └──────────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## التحديات التقنية والتجارية المحتملة
|
||||||
|
|
||||||
|
| التحدي | الحل المقترح |
|
||||||
|
|--------|--------------|
|
||||||
|
| **توافق PHP** | دعم PHP 8.1+ المتوفر على غيمة |
|
||||||
|
| **Cache** | استخدام Redis من غيمة للتخزين المؤقت |
|
||||||
|
| **Rate Limiting** | تنسيق مع mithal.space لحدود API |
|
||||||
|
| **التوثيق** | إنشاء توثيق مشترك بالعربية |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## لماذا هذا المنتج الأكثر قابلية للتطبيق؟ ✅
|
||||||
|
|
||||||
|
| السبب | التفسير |
|
||||||
|
|-------|---------|
|
||||||
|
| **1. البنية التحتية** | إطار العمل يحتاج استضافة، وغيمة توفرها مباشرة |
|
||||||
|
| **2. المطورين العرب** | Green موجه للمطورين العرب، وغيمة كذلك = تكامل طبيعي |
|
||||||
|
| **3. سهولة التنفيذ** | إنشاء template جاهز أسهل من تكامل AI معقد |
|
||||||
|
| **4. القيمة المتبادلة** | Green يحصل على استضافة، غيمة تحصل على مستخدمين |
|
||||||
|
| **5. التوسع** | كل تطبيق يُبنى بـ Green يمكن استضافته على غيمة |
|
||||||
|
| **6. التكامل مع mithal** | إضافة بحث عربي يحترم الخصوصية = ميزة تنافسية |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## خطة التنفيذ المقترحة
|
||||||
|
|
||||||
|
| المرحلة | المدة | المهام |
|
||||||
|
|---------|-------|--------|
|
||||||
|
| **المرحلة 1** | أسبوع 1-2 | إنشاء Ghaymah Template لـ Green + توثيق خطوات النشر |
|
||||||
|
| **المرحلة 2** | أسبوع 3-4 | تطوير mithal-search package + اختبار التكامل |
|
||||||
|
| **المرحلة 3** | أسبوع 5-6 | إطلاق رسمي + حملة تسويقية مشتركة |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخلاصة
|
||||||
|
|
||||||
|
التكامل بين **Green Framework** و **Ghaymah Cloud** و **mithal.space** يخلق منظومة متكاملة للمطورين العرب تدعم **السيادة الرقمية العربية** وتوفر بديلاً محلياً للحلول الأجنبية.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Qabilah Profile: @ahmedmibrahim
|
||||||
|
URL: https://qabilah.com/profile/ahmedmibrahim
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# فحص أمني تلقائي لتطبيق منشور على غيمة (ghaymah.systems)
|
||||||
|
# يفحص: المنافذ، SSL، الصلاحيات
|
||||||
|
|
||||||
|
DOMAIN="${1:-myapp.ghaymah.systems}"
|
||||||
|
echo "╔════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ فحص أمني تلقائي لتطبيق على غيمة ║"
|
||||||
|
echo "║ Target: $DOMAIN"
|
||||||
|
echo "╚════════════════════════════════════════════════════════════╝"
|
||||||
|
|
||||||
|
PASS=0
|
||||||
|
WARN=0
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
# دالة للطباعة الملونة
|
||||||
|
print_result() {
|
||||||
|
case $1 in
|
||||||
|
"pass") echo -e "✅ \e[32m$2\e[0m"; ((PASS++));;
|
||||||
|
"warn") echo -e "⚠️ \e[33m$2\e[0m"; ((WARN++));;
|
||||||
|
"fail") echo -e "❌ \e[31m$2\e[0m"; ((FAIL++));;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 1. فحص المنافذ المفتوحة
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
echo -e "\n━━━ [1/3] فحص المنافذ ━━━"
|
||||||
|
|
||||||
|
check_port() {
|
||||||
|
local port=$1
|
||||||
|
local expected=$2
|
||||||
|
timeout 2 bash -c "echo >/dev/tcp/$DOMAIN/$port" 2>/dev/null
|
||||||
|
local result=$?
|
||||||
|
|
||||||
|
if [ $result -eq 0 ]; then
|
||||||
|
if [ "$expected" = "open" ]; then
|
||||||
|
print_result "pass" "المنفذ $port مفتوح (متوقع)"
|
||||||
|
else
|
||||||
|
print_result "fail" "المنفذ $port مفتوح (يجب أن يكون مغلقاً!)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$expected" = "closed" ]; then
|
||||||
|
print_result "pass" "المنفذ $port مغلق (آمن)"
|
||||||
|
else
|
||||||
|
print_result "warn" "المنفذ $port مغلق (قد يكون مشكلة)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# المنافذ المتوقع أن تكون مفتوحة
|
||||||
|
check_port 80 "open"
|
||||||
|
check_port 443 "open"
|
||||||
|
|
||||||
|
# المنافذ التي يجب أن تكون مغلقة (قواعد البيانات)
|
||||||
|
check_port 22 "closed" # SSH
|
||||||
|
check_port 3306 "closed" # MySQL
|
||||||
|
check_port 5432 "closed" # PostgreSQL
|
||||||
|
check_port 6379 "closed" # Redis
|
||||||
|
check_port 27017 "closed" # MongoDB
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 2. فحص شهادة SSL
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
echo -e "\n━━━ [2/3] فحص شهادة SSL ━━━"
|
||||||
|
|
||||||
|
ssl_info=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -z "$ssl_info" ]; then
|
||||||
|
print_result "fail" "لا يمكن الاتصال بـ SSL"
|
||||||
|
else
|
||||||
|
# التحقق من صحة الشهادة
|
||||||
|
verify_result=$(echo "$ssl_info" | grep "Verify return code")
|
||||||
|
if echo "$verify_result" | grep -q "0 (ok)"; then
|
||||||
|
print_result "pass" "شهادة SSL صالحة"
|
||||||
|
else
|
||||||
|
print_result "fail" "شهادة SSL غير صالحة: $verify_result"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# تاريخ انتهاء الشهادة
|
||||||
|
expiry=$(echo "$ssl_info" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
|
||||||
|
if [ -n "$expiry" ]; then
|
||||||
|
expiry_epoch=$(date -d "$expiry" +%s 2>/dev/null)
|
||||||
|
now_epoch=$(date +%s)
|
||||||
|
days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
|
||||||
|
|
||||||
|
if [ $days_left -gt 30 ]; then
|
||||||
|
print_result "pass" "الشهادة صالحة لـ $days_left يوم"
|
||||||
|
elif [ $days_left -gt 7 ]; then
|
||||||
|
print_result "warn" "الشهادة تنتهي خلال $days_left يوم"
|
||||||
|
else
|
||||||
|
print_result "fail" "الشهادة تنتهي خلال $days_left يوم فقط!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# إصدار TLS
|
||||||
|
tls_version=$(echo "$ssl_info" | grep "Protocol" | awk '{print $3}')
|
||||||
|
if [[ "$tls_version" == "TLSv1.3" ]]; then
|
||||||
|
print_result "pass" "يستخدم TLS 1.3 (الأحدث)"
|
||||||
|
elif [[ "$tls_version" == "TLSv1.2" ]]; then
|
||||||
|
print_result "pass" "يستخدم TLS 1.2 (مقبول)"
|
||||||
|
else
|
||||||
|
print_result "warn" "يستخدم $tls_version (قديم)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 3. فحص Security Headers
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
echo -e "\n━━━ [3/3] فحص Security Headers ━━━"
|
||||||
|
|
||||||
|
headers=$(curl -sI "https://$DOMAIN" 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -z "$headers" ]; then
|
||||||
|
print_result "fail" "لا يمكن جلب الـ headers"
|
||||||
|
else
|
||||||
|
# Strict-Transport-Security
|
||||||
|
if echo "$headers" | grep -qi "Strict-Transport-Security"; then
|
||||||
|
print_result "pass" "HSTS مفعّل"
|
||||||
|
else
|
||||||
|
print_result "warn" "HSTS غير مفعّل"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# X-Content-Type-Options
|
||||||
|
if echo "$headers" | grep -qi "X-Content-Type-Options"; then
|
||||||
|
print_result "pass" "X-Content-Type-Options موجود"
|
||||||
|
else
|
||||||
|
print_result "warn" "X-Content-Type-Options غير موجود"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# X-Frame-Options
|
||||||
|
if echo "$headers" | grep -qi "X-Frame-Options"; then
|
||||||
|
print_result "pass" "X-Frame-Options موجود (حماية من Clickjacking)"
|
||||||
|
else
|
||||||
|
print_result "warn" "X-Frame-Options غير موجود"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Content-Security-Policy
|
||||||
|
if echo "$headers" | grep -qi "Content-Security-Policy"; then
|
||||||
|
print_result "pass" "CSP مفعّل"
|
||||||
|
else
|
||||||
|
print_result "warn" "CSP غير مفعّل"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# X-Powered-By (يجب أن يكون مخفياً)
|
||||||
|
if echo "$headers" | grep -qi "X-Powered-By"; then
|
||||||
|
powered_by=$(echo "$headers" | grep -i "X-Powered-By")
|
||||||
|
print_result "fail" "X-Powered-By مكشوف: $powered_by"
|
||||||
|
else
|
||||||
|
print_result "pass" "X-Powered-By مخفي (آمن)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Server header
|
||||||
|
if echo "$headers" | grep -qi "^Server:"; then
|
||||||
|
server=$(echo "$headers" | grep -i "^Server:" | head -1)
|
||||||
|
print_result "warn" "Server header مكشوف: $server"
|
||||||
|
else
|
||||||
|
print_result "pass" "Server header مخفي"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# ملخص النتائج
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
echo -e "\n╔════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ ملخص الفحص ║"
|
||||||
|
echo "╠════════════════════════════════════════════════════════════╣"
|
||||||
|
echo -e "║ ✅ نجح: $PASS "
|
||||||
|
echo -e "║ ⚠️ تحذير: $WARN "
|
||||||
|
echo -e "║ ❌ فشل: $FAIL "
|
||||||
|
echo "╚════════════════════════════════════════════════════════════╝"
|
||||||
|
|
||||||
|
# Exit code based on failures
|
||||||
|
if [ $FAIL -gt 0 ]; then
|
||||||
|
echo -e "\n⛔ يوجد مشاكل أمنية يجب معالجتها!"
|
||||||
|
exit 1
|
||||||
|
elif [ $WARN -gt 0 ]; then
|
||||||
|
echo -e "\n⚡ يوجد تحذيرات يُنصح بمراجعتها"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo -e "\n🎉 جميع الفحوصات ناجحة!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
# قائمة تدقيق أمني لتطبيق على منصة غيمة (ghaymah.systems)
|
||||||
|
|
||||||
|
## قائمة من 15 بنداً للتدقيق الأمني
|
||||||
|
|
||||||
|
| # | البند | الفئة | الأولوية |
|
||||||
|
|---|-------|-------|----------|
|
||||||
|
| 1 | التحقق من تفعيل شهادة SSL التلقائية من غيمة | Data | عالية |
|
||||||
|
| 2 | تشفير البيانات في PostgreSQL المُدارة (Encryption at Rest) | Data | عالية |
|
||||||
|
| 3 | تشفير اتصالات Redis/Valkey | Data | متوسطة |
|
||||||
|
| 4 | مراجعة صلاحيات الوصول للـ Git Repository المرتبط بالنشر | IAM | عالية |
|
||||||
|
| 5 | تفعيل MFA على حساب غيمة (deploy.ghaymah.systems) | IAM | عالية |
|
||||||
|
| 6 | فحص Docker Images المستخدمة من الثغرات (Trivy/Snyk) | Container Security | عالية |
|
||||||
|
| 7 | عدم تشغيل الحاويات بصلاحيات root | Container Security | عالية |
|
||||||
|
| 8 | تقييد المنافذ المفتوحة (فقط 80/443) | Network | عالية |
|
||||||
|
| 9 | تكوين Network Policies بين الخدمات | Network | متوسطة |
|
||||||
|
| 10 | الحماية من SQL Injection | OWASP | عالية |
|
||||||
|
| 11 | الحماية من XSS وتفعيل CSP Headers | OWASP | عالية |
|
||||||
|
| 12 | تفعيل Rate Limiting على APIs | OWASP | عالية |
|
||||||
|
| 13 | إخفاء Server Headers (X-Powered-By) | OWASP | متوسطة |
|
||||||
|
| 14 | التحقق من تفعيل النسخ الاحتياطي التلقائي | Data | عالية |
|
||||||
|
| 15 | مراجعة سجلات المراقبة والتنبيهات | Data | متوسطة |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## شرح تطبيق كل بند على منصة غيمة تحديداً
|
||||||
|
|
||||||
|
### 1. SSL التلقائية
|
||||||
|
غيمة توفر شهادة SSL تلقائية لجميع الخطط. للتحقق:
|
||||||
|
- تأكد من أن الدومين يعمل على HTTPS فقط
|
||||||
|
- أضف redirect من HTTP إلى HTTPS
|
||||||
|
- تحقق من صلاحية الشهادة عبر المتصفح
|
||||||
|
|
||||||
|
### 2. PostgreSQL المُدارة
|
||||||
|
- تفعيل خيار "اتصالات مشفّرة" في إعدادات قاعدة البيانات
|
||||||
|
- استخدام SSL mode في connection string:
|
||||||
|
```
|
||||||
|
postgresql://user:pass@host:5432/db?sslmode=require
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Redis/Valkey
|
||||||
|
- استخدام الاتصال المشفر الافتراضي من غيمة
|
||||||
|
- التأكد من أن Redis غير مكشوف للإنترنت
|
||||||
|
|
||||||
|
### 4. Git Repository
|
||||||
|
- مراجعة من لديه صلاحية push على الـ repo
|
||||||
|
- تفعيل branch protection على main/master
|
||||||
|
- استخدام deploy keys بدلاً من personal tokens
|
||||||
|
|
||||||
|
### 5. MFA
|
||||||
|
- تفعيله من إعدادات حساب غيمة
|
||||||
|
- استخدام تطبيق authenticator (Google/Microsoft)
|
||||||
|
|
||||||
|
### 6. Container Scanning
|
||||||
|
إضافة في CI/CD pipeline:
|
||||||
|
```yaml
|
||||||
|
- name: Scan image
|
||||||
|
run: trivy image myapp:latest --severity HIGH,CRITICAL
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Non-root Containers
|
||||||
|
في Dockerfile:
|
||||||
|
```dockerfile
|
||||||
|
USER nonroot:nonroot
|
||||||
|
# أو
|
||||||
|
USER 1000:1000
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. المنافذ
|
||||||
|
- غيمة تدير هذا تلقائياً
|
||||||
|
- تأكد من عدم expose منافذ إضافية في Dockerfile
|
||||||
|
- لا تستخدم `EXPOSE` لمنافذ حساسة
|
||||||
|
|
||||||
|
### 9. Network Policies
|
||||||
|
- فصل PostgreSQL عن الإنترنت العام (internal only)
|
||||||
|
- السماح فقط للـ backend بالوصول لقاعدة البيانات
|
||||||
|
|
||||||
|
### 10. SQL Injection
|
||||||
|
- استخدام ORM (Prisma, Sequelize, SQLAlchemy)
|
||||||
|
- أو Prepared Statements:
|
||||||
|
```javascript
|
||||||
|
db.query('SELECT * FROM users WHERE id = $1', [userId])
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11. XSS/CSP
|
||||||
|
إضافة headers في التطبيق:
|
||||||
|
```javascript
|
||||||
|
app.use(helmet({
|
||||||
|
contentSecurityPolicy: {
|
||||||
|
directives: {
|
||||||
|
defaultSrc: ["'self'"],
|
||||||
|
scriptSrc: ["'self'"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
### 12. Rate Limiting
|
||||||
|
```javascript
|
||||||
|
const rateLimit = require('express-rate-limit');
|
||||||
|
app.use('/api/login', rateLimit({
|
||||||
|
windowMs: 15 * 60 * 1000,
|
||||||
|
max: 5
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
### 13. Server Headers
|
||||||
|
```javascript
|
||||||
|
app.disable('x-powered-by');
|
||||||
|
// أو استخدام helmet
|
||||||
|
app.use(helmet.hidePoweredBy());
|
||||||
|
```
|
||||||
|
|
||||||
|
### 14. النسخ الاحتياطي
|
||||||
|
- خطة g4.medium: نسخ يومي
|
||||||
|
- خطة g5.large: نسخ كل ساعة
|
||||||
|
- تحقق من إعدادات النسخ في لوحة التحكم
|
||||||
|
|
||||||
|
### 15. المراقبة
|
||||||
|
- استخدام أدوات الذكاء الاصطناعي والمراقبة المتوفرة في غيمة
|
||||||
|
- إعداد تنبيهات للأحداث المشبوهة
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
# Alert Rules لاكتشاف هجمات Brute Force
|
||||||
|
# للتطبيقات المنشورة على غيمة (ghaymah.systems)
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Prometheus Alert Rules
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
groups:
|
||||||
|
- name: ghaymah_brute_force_detection
|
||||||
|
interval: 30s
|
||||||
|
rules:
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
# 1. اكتشاف محاولات تسجيل دخول فاشلة متكررة
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
- alert: BruteForceDetected
|
||||||
|
expr: |
|
||||||
|
sum(rate(http_requests_total{
|
||||||
|
path="/api/login",
|
||||||
|
status=~"401|403"
|
||||||
|
}[5m])) by (source_ip) > 10
|
||||||
|
for: 2m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
team: security
|
||||||
|
platform: ghaymah
|
||||||
|
annotations:
|
||||||
|
summary: "🚨 هجوم Brute Force محتمل"
|
||||||
|
description: |
|
||||||
|
IP {{ $labels.source_ip }} أرسل أكثر من 10 محاولات فاشلة
|
||||||
|
في آخر 5 دقائق على /api/login
|
||||||
|
value: "{{ $value }} محاولة/دقيقة"
|
||||||
|
runbook_url: "https://wiki.internal/runbooks/brute-force"
|
||||||
|
action: |
|
||||||
|
1. حظر IP فوراً
|
||||||
|
2. مراجعة الـ logs
|
||||||
|
3. التحقق من الحسابات المستهدفة
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
# 2. اكتشاف نجاح تسجيل دخول بعد محاولات فاشلة
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
- alert: SuspiciousLoginAfterFailures
|
||||||
|
expr: |
|
||||||
|
(
|
||||||
|
sum(increase(http_requests_total{
|
||||||
|
path="/api/login",
|
||||||
|
status="200"
|
||||||
|
}[1m])) by (source_ip) > 0
|
||||||
|
)
|
||||||
|
and
|
||||||
|
(
|
||||||
|
sum(increase(http_requests_total{
|
||||||
|
path="/api/login",
|
||||||
|
status="401"
|
||||||
|
}[10m])) by (source_ip) > 5
|
||||||
|
)
|
||||||
|
for: 0m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
team: security
|
||||||
|
annotations:
|
||||||
|
summary: "⚠️ تسجيل دخول مشبوه بعد محاولات فاشلة"
|
||||||
|
description: |
|
||||||
|
IP {{ $labels.source_ip }} نجح في تسجيل الدخول
|
||||||
|
بعد عدة محاولات فاشلة - قد يكون هجوم ناجح!
|
||||||
|
action: |
|
||||||
|
1. مراجعة الحساب المستخدم فوراً
|
||||||
|
2. التحقق من النشاط بعد الدخول
|
||||||
|
3. النظر في إلغاء الـ session
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
# 3. اكتشاف طلبات كثيرة من IP واحد
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
- alert: HighRequestRateFromSingleIP
|
||||||
|
expr: |
|
||||||
|
sum(rate(http_requests_total[1m])) by (source_ip) > 100
|
||||||
|
for: 1m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
team: security
|
||||||
|
annotations:
|
||||||
|
summary: "📊 معدل طلبات عالي من IP واحد"
|
||||||
|
description: |
|
||||||
|
IP {{ $labels.source_ip }} يرسل {{ $value }} طلب/دقيقة
|
||||||
|
قد يكون هجوم DDoS أو scraping
|
||||||
|
action: "مراقبة وحظر إذا استمر"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
# 4. اكتشاف محاولات الوصول لـ endpoints حساسة
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
- alert: SensitiveEndpointAccess
|
||||||
|
expr: |
|
||||||
|
sum(rate(http_requests_total{
|
||||||
|
path=~"/api/admin.*|/api/users/export|/api/config"
|
||||||
|
}[5m])) by (source_ip, path) > 5
|
||||||
|
for: 1m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
team: security
|
||||||
|
annotations:
|
||||||
|
summary: "🔐 محاولات وصول لـ endpoints حساسة"
|
||||||
|
description: |
|
||||||
|
IP {{ $labels.source_ip }} يحاول الوصول لـ {{ $labels.path }}
|
||||||
|
action: "التحقق من صلاحيات المستخدم"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
# 5. اكتشاف User-Agent مشبوه
|
||||||
|
# ─────────────────────────────────────────────────────────
|
||||||
|
- alert: SuspiciousUserAgent
|
||||||
|
expr: |
|
||||||
|
sum(rate(http_requests_total{
|
||||||
|
user_agent=~".*curl.*|.*python.*|.*wget.*|.*nikto.*|.*sqlmap.*"
|
||||||
|
}[5m])) by (source_ip, user_agent) > 10
|
||||||
|
for: 2m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
team: security
|
||||||
|
annotations:
|
||||||
|
summary: "🤖 User-Agent مشبوه"
|
||||||
|
description: |
|
||||||
|
IP {{ $labels.source_ip }} يستخدم {{ $labels.user_agent }}
|
||||||
|
قد يكون أداة هجوم آلية
|
||||||
|
|
||||||
|
---
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Alertmanager Configuration
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# alertmanager.yml
|
||||||
|
global:
|
||||||
|
resolve_timeout: 5m
|
||||||
|
|
||||||
|
route:
|
||||||
|
group_by: ['alertname', 'severity']
|
||||||
|
group_wait: 10s
|
||||||
|
group_interval: 10s
|
||||||
|
repeat_interval: 1h
|
||||||
|
receiver: 'security-team'
|
||||||
|
routes:
|
||||||
|
- match:
|
||||||
|
severity: critical
|
||||||
|
receiver: 'security-critical'
|
||||||
|
continue: true
|
||||||
|
|
||||||
|
receivers:
|
||||||
|
- name: 'security-team'
|
||||||
|
email_configs:
|
||||||
|
- to: 'security@company.com'
|
||||||
|
subject: '[Ghaymah Alert] {{ .GroupLabels.alertname }}'
|
||||||
|
|
||||||
|
- name: 'security-critical'
|
||||||
|
email_configs:
|
||||||
|
- to: 'security-oncall@company.com'
|
||||||
|
webhook_configs:
|
||||||
|
- url: 'https://hooks.slack.com/services/xxx/yyy/zzz'
|
||||||
|
send_resolved: true
|
||||||
|
# إرسال SMS للحالات الحرجة
|
||||||
|
# pagerduty_configs:
|
||||||
|
# - service_key: 'your-pagerduty-key'
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
# خطة الاستجابة للحوادث - Incident Response Plan
|
||||||
|
|
||||||
|
## نوع الحادثة
|
||||||
|
هجوم Brute Force ناجح على API Login أدى إلى تسريب بيانات
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## المرحلة 1: الاحتواء (Containment) - أول 30 دقيقة
|
||||||
|
|
||||||
|
### الإجراءات الفورية:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. إلغاء جميع الـ JWT tokens النشطة
|
||||||
|
# في قاعدة البيانات أو Redis
|
||||||
|
redis-cli FLUSHDB # إذا كانت sessions في Redis
|
||||||
|
|
||||||
|
# أو عبر API إداري
|
||||||
|
curl -X POST https://app.ghaymah.systems/api/admin/invalidate-all-tokens \
|
||||||
|
-H "Authorization: Bearer $ADMIN_TOKEN"
|
||||||
|
|
||||||
|
# 2. حظر IP المهاجم
|
||||||
|
# في iptables
|
||||||
|
sudo iptables -A INPUT -s 192.168.1.100 -j DROP
|
||||||
|
|
||||||
|
# أو في nginx
|
||||||
|
echo "deny 192.168.1.100;" >> /etc/nginx/conf.d/blocked-ips.conf
|
||||||
|
sudo nginx -s reload
|
||||||
|
|
||||||
|
# 3. تعطيل الحساب المخترق
|
||||||
|
UPDATE users SET status = 'suspended',
|
||||||
|
password_hash = 'COMPROMISED_RESET_REQUIRED'
|
||||||
|
WHERE username = 'admin';
|
||||||
|
```
|
||||||
|
|
||||||
|
### قائمة التحقق:
|
||||||
|
- [ ] إلغاء جميع الـ tokens
|
||||||
|
- [ ] حظر IP المهاجم
|
||||||
|
- [ ] تعطيل الحساب المخترق
|
||||||
|
- [ ] إبلاغ فريق الأمن
|
||||||
|
- [ ] توثيق وقت الاكتشاف
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## المرحلة 2: التحقيق (Investigation) - 1-4 ساعات
|
||||||
|
|
||||||
|
### جمع الأدلة:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. حفظ الـ logs
|
||||||
|
cp /var/log/nginx/access.log /incident/access.log.$(date +%Y%m%d)
|
||||||
|
cp /var/log/nginx/error.log /incident/error.log.$(date +%Y%m%d)
|
||||||
|
|
||||||
|
# 2. تحليل الطلبات المشبوهة
|
||||||
|
grep "POST /api/login" /var/log/nginx/access.log | \
|
||||||
|
awk '{print $1}' | sort | uniq -c | sort -rn | head -20
|
||||||
|
|
||||||
|
# 3. تتبع نشاط المهاجم بعد الدخول
|
||||||
|
grep "192.168.1.100" /var/log/nginx/access.log | \
|
||||||
|
grep -E "200|201" > /incident/attacker-activity.log
|
||||||
|
|
||||||
|
# 4. تحديد البيانات المسربة
|
||||||
|
grep "192.168.1.100" /var/log/nginx/access.log | \
|
||||||
|
grep -E "/api/users|/api/export"
|
||||||
|
```
|
||||||
|
|
||||||
|
### الأسئلة المطلوب الإجابة عليها:
|
||||||
|
1. متى بدأ الهجوم؟
|
||||||
|
2. كم محاولة تمت قبل النجاح؟
|
||||||
|
3. ما البيانات التي تم الوصول إليها؟
|
||||||
|
4. هل يوجد backdoors؟
|
||||||
|
5. هل تأثرت أنظمة أخرى؟
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## المرحلة 3: الاستئصال (Eradication) - 4-8 ساعات
|
||||||
|
|
||||||
|
### الإجراءات:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. إعادة تعيين كلمات مرور جميع المستخدمين
|
||||||
|
# إرسال بريد إلكتروني لجميع المستخدمين
|
||||||
|
|
||||||
|
# 2. فحص النظام من backdoors
|
||||||
|
# فحص cron jobs
|
||||||
|
crontab -l
|
||||||
|
cat /etc/crontab
|
||||||
|
|
||||||
|
# فحص authorized_keys
|
||||||
|
cat ~/.ssh/authorized_keys
|
||||||
|
|
||||||
|
# فحص الملفات المعدلة مؤخراً
|
||||||
|
find /app -mtime -1 -type f
|
||||||
|
|
||||||
|
# 3. تحديث التبعيات
|
||||||
|
npm audit fix
|
||||||
|
# أو
|
||||||
|
pip install --upgrade -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### قائمة التحقق:
|
||||||
|
- [ ] إعادة تعيين كلمات المرور
|
||||||
|
- [ ] فحص backdoors
|
||||||
|
- [ ] مراجعة صلاحيات المستخدمين
|
||||||
|
- [ ] تحديث التبعيات الأمنية
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## المرحلة 4: الاستعادة (Recovery) - 8-24 ساعة
|
||||||
|
|
||||||
|
### خطوات الاستعادة:
|
||||||
|
|
||||||
|
1. **تفعيل الحماية الجديدة:**
|
||||||
|
```javascript
|
||||||
|
// إضافة Rate Limiting
|
||||||
|
const rateLimit = require('express-rate-limit');
|
||||||
|
app.use('/api/login', rateLimit({
|
||||||
|
windowMs: 15 * 60 * 1000,
|
||||||
|
max: 5,
|
||||||
|
message: 'محاولات كثيرة، حاول لاحقاً'
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **تفعيل Account Lockout:**
|
||||||
|
```javascript
|
||||||
|
// قفل الحساب بعد 5 محاولات فاشلة
|
||||||
|
if (failedAttempts >= 5) {
|
||||||
|
await lockAccount(userId, 30 * 60 * 1000); // 30 دقيقة
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **إعادة تشغيل الخدمات:**
|
||||||
|
```bash
|
||||||
|
# إعادة نشر التطبيق على غيمة
|
||||||
|
git push origin main # النشر التلقائي
|
||||||
|
```
|
||||||
|
|
||||||
|
### قائمة التحقق:
|
||||||
|
- [ ] تفعيل Rate Limiting
|
||||||
|
- [ ] تفعيل Account Lockout
|
||||||
|
- [ ] إضافة CAPTCHA
|
||||||
|
- [ ] تفعيل MFA للحسابات الإدارية
|
||||||
|
- [ ] إعادة تشغيل الخدمات
|
||||||
|
- [ ] اختبار الحماية الجديدة
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## المرحلة 5: إبلاغ المتأثرين - 24-48 ساعة
|
||||||
|
|
||||||
|
### نموذج البريد الإلكتروني:
|
||||||
|
|
||||||
|
```
|
||||||
|
الموضوع: إشعار أمني مهم - [اسم التطبيق]
|
||||||
|
|
||||||
|
عزيزي المستخدم،
|
||||||
|
|
||||||
|
نود إبلاغك بحادثة أمنية وقعت بتاريخ [التاريخ].
|
||||||
|
تم الوصول غير المصرح به إلى بعض بيانات المستخدمين.
|
||||||
|
|
||||||
|
البيانات المتأثرة:
|
||||||
|
- الاسم
|
||||||
|
- البريد الإلكتروني
|
||||||
|
- [أي بيانات أخرى]
|
||||||
|
|
||||||
|
الإجراءات المتخذة:
|
||||||
|
1. تم إيقاف الهجوم فوراً
|
||||||
|
2. تم تعزيز الحماية
|
||||||
|
3. تم إعادة تعيين جميع كلمات المرور
|
||||||
|
|
||||||
|
ما يجب عليك فعله:
|
||||||
|
1. تغيير كلمة المرور فوراً
|
||||||
|
2. تفعيل المصادقة الثنائية
|
||||||
|
3. مراقبة حساباتك الأخرى
|
||||||
|
|
||||||
|
نعتذر عن أي إزعاج.
|
||||||
|
|
||||||
|
فريق الأمن
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## المرحلة 6: الدروس المستفادة - أسبوع
|
||||||
|
|
||||||
|
### اجتماع Post-Mortem:
|
||||||
|
|
||||||
|
| السؤال | الإجابة |
|
||||||
|
|--------|---------|
|
||||||
|
| ما الذي حدث؟ | هجوم brute force ناجح |
|
||||||
|
| لماذا حدث؟ | عدم وجود rate limiting + كلمة مرور ضعيفة |
|
||||||
|
| كيف اكتشفناه؟ | مراجعة يدوية للـ logs |
|
||||||
|
| كم استغرق الاحتواء؟ | [X] دقيقة |
|
||||||
|
| ما الذي يجب تحسينه؟ | إضافة تنبيهات تلقائية |
|
||||||
|
|
||||||
|
### التحسينات المطلوبة:
|
||||||
|
1. [ ] تفعيل Rate Limiting على جميع APIs
|
||||||
|
2. [ ] فرض سياسة كلمات مرور قوية
|
||||||
|
3. [ ] تفعيل MFA إلزامياً للإداريين
|
||||||
|
4. [ ] إضافة تنبيهات للنشاط المشبوه
|
||||||
|
5. [ ] تدريب الفريق على الاستجابة للحوادث
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## جهات الاتصال
|
||||||
|
|
||||||
|
| الدور | الاسم | الهاتف | البريد |
|
||||||
|
|-------|-------|--------|--------|
|
||||||
|
| قائد الحادثة | [الاسم] | [الرقم] | [البريد] |
|
||||||
|
| فريق DevOps | [الاسم] | [الرقم] | [البريد] |
|
||||||
|
| المستشار القانوني | [الاسم] | [الرقم] | [البريد] |
|
||||||
|
| دعم غيمة | - | - | support@ghaymah.systems |
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
# Network Policies & Container Security لمنع هجمات Brute Force
|
||||||
|
# للتطبيقات المنشورة على غيمة (ghaymah.systems)
|
||||||
|
|
||||||
|
---
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 1. Network Policy - عزل قاعدة البيانات
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: database-isolation
|
||||||
|
namespace: ghaymah-app
|
||||||
|
labels:
|
||||||
|
app: security-policy
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgresql
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
# السماح فقط للـ backend بالوصول لقاعدة البيانات
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: backend-api
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
egress:
|
||||||
|
# منع قاعدة البيانات من الاتصال بالخارج
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: backend-api
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
|
||||||
|
---
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 2. Network Policy - حماية API Login
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: api-login-protection
|
||||||
|
namespace: ghaymah-app
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: login-api
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
# السماح فقط من خلال API Gateway/Ingress
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: ingress-nginx
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: api-gateway
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
---
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 3. Network Policy - عزل Redis
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: redis-isolation
|
||||||
|
namespace: ghaymah-app
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: redis
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: backend-api
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 6379
|
||||||
|
|
||||||
|
---
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 4. Pod Security Policy - منع تشغيل root
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
apiVersion: policy/v1beta1
|
||||||
|
kind: PodSecurityPolicy
|
||||||
|
metadata:
|
||||||
|
name: restricted-psp
|
||||||
|
spec:
|
||||||
|
privileged: false
|
||||||
|
runAsUser:
|
||||||
|
rule: MustRunAsNonRoot
|
||||||
|
runAsGroup:
|
||||||
|
rule: MustRunAs
|
||||||
|
ranges:
|
||||||
|
- min: 1000
|
||||||
|
max: 65535
|
||||||
|
fsGroup:
|
||||||
|
rule: MustRunAs
|
||||||
|
ranges:
|
||||||
|
- min: 1000
|
||||||
|
max: 65535
|
||||||
|
seLinux:
|
||||||
|
rule: RunAsAny
|
||||||
|
volumes:
|
||||||
|
- 'configMap'
|
||||||
|
- 'emptyDir'
|
||||||
|
- 'secret'
|
||||||
|
- 'persistentVolumeClaim'
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
requiredDropCapabilities:
|
||||||
|
- ALL
|
||||||
|
|
||||||
|
---
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 5. Security Context للـ Deployment
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: secure-api
|
||||||
|
namespace: ghaymah-app
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: backend-api
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: backend-api
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: api
|
||||||
|
image: myapp:latest
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: "500m"
|
||||||
|
memory: "512Mi"
|
||||||
|
requests:
|
||||||
|
cpu: "100m"
|
||||||
|
memory: "128Mi"
|
||||||
|
volumeMounts:
|
||||||
|
- name: tmp
|
||||||
|
mountPath: /tmp
|
||||||
|
volumes:
|
||||||
|
- name: tmp
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
---
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 6. Rate Limiting في Ingress (nginx)
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: api-ingress
|
||||||
|
namespace: ghaymah-app
|
||||||
|
annotations:
|
||||||
|
# Rate limiting
|
||||||
|
nginx.ingress.kubernetes.io/limit-rps: "10"
|
||||||
|
nginx.ingress.kubernetes.io/limit-connections: "5"
|
||||||
|
# حماية من الهجمات
|
||||||
|
nginx.ingress.kubernetes.io/server-snippet: |
|
||||||
|
# حظر User-Agents المشبوهة
|
||||||
|
if ($http_user_agent ~* (curl|wget|python|nikto|sqlmap)) {
|
||||||
|
return 403;
|
||||||
|
}
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: app.ghaymah.systems
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /api
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: backend-api
|
||||||
|
port:
|
||||||
|
number: 8080
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
/**
|
||||||
|
* Rate Limiter Middleware للحماية من Brute Force
|
||||||
|
* للتطبيقات المنشورة على غيمة (ghaymah.systems)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const rateLimit = require('express-rate-limit');
|
||||||
|
const RedisStore = require('rate-limit-redis');
|
||||||
|
const Redis = require('ioredis');
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// إعداد Redis (من غيمة)
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
const redis = new Redis(process.env.GHAYMAH_REDIS_URL || 'redis://localhost:6379');
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// Rate Limiter لـ Login API
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
const loginLimiter = rateLimit({
|
||||||
|
store: new RedisStore({
|
||||||
|
sendCommand: (...args) => redis.call(...args),
|
||||||
|
prefix: 'rl:login:'
|
||||||
|
}),
|
||||||
|
|
||||||
|
// 5 محاولات كل 15 دقيقة
|
||||||
|
windowMs: 15 * 60 * 1000,
|
||||||
|
max: 5,
|
||||||
|
|
||||||
|
// رسالة الخطأ
|
||||||
|
message: {
|
||||||
|
error: 'محاولات كثيرة جداً',
|
||||||
|
message: 'تم حظرك مؤقتاً. حاول مرة أخرى بعد 15 دقيقة',
|
||||||
|
retryAfter: 15 * 60
|
||||||
|
},
|
||||||
|
|
||||||
|
// Headers قياسية
|
||||||
|
standardHeaders: true,
|
||||||
|
legacyHeaders: false,
|
||||||
|
|
||||||
|
// تخطي الطلبات الناجحة
|
||||||
|
skipSuccessfulRequests: false,
|
||||||
|
|
||||||
|
// معالج مخصص عند تجاوز الحد
|
||||||
|
handler: (req, res, next, options) => {
|
||||||
|
// تسجيل للمراقبة
|
||||||
|
console.warn(`[SECURITY] Rate limit exceeded`, {
|
||||||
|
ip: req.ip,
|
||||||
|
path: req.path,
|
||||||
|
userAgent: req.get('User-Agent'),
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
});
|
||||||
|
|
||||||
|
// إرسال metric لـ Prometheus
|
||||||
|
if (global.metrics) {
|
||||||
|
global.metrics.rateLimitExceeded.inc({
|
||||||
|
path: '/api/login',
|
||||||
|
ip: req.ip
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(429).json(options.message);
|
||||||
|
},
|
||||||
|
|
||||||
|
// تحديد المفتاح (IP + username إن وجد)
|
||||||
|
keyGenerator: (req) => {
|
||||||
|
const username = req.body?.username || 'unknown';
|
||||||
|
return `${req.ip}:${username}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// Rate Limiter عام للـ API
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
const apiLimiter = rateLimit({
|
||||||
|
store: new RedisStore({
|
||||||
|
sendCommand: (...args) => redis.call(...args),
|
||||||
|
prefix: 'rl:api:'
|
||||||
|
}),
|
||||||
|
|
||||||
|
// 100 طلب كل دقيقة
|
||||||
|
windowMs: 60 * 1000,
|
||||||
|
max: 100,
|
||||||
|
|
||||||
|
message: {
|
||||||
|
error: 'طلبات كثيرة',
|
||||||
|
message: 'تجاوزت الحد المسموح. حاول لاحقاً'
|
||||||
|
},
|
||||||
|
|
||||||
|
standardHeaders: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// Rate Limiter للـ endpoints الحساسة
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
const sensitiveEndpointLimiter = rateLimit({
|
||||||
|
store: new RedisStore({
|
||||||
|
sendCommand: (...args) => redis.call(...args),
|
||||||
|
prefix: 'rl:sensitive:'
|
||||||
|
}),
|
||||||
|
|
||||||
|
// 10 طلبات كل 5 دقائق
|
||||||
|
windowMs: 5 * 60 * 1000,
|
||||||
|
max: 10,
|
||||||
|
|
||||||
|
message: {
|
||||||
|
error: 'وصول محدود',
|
||||||
|
message: 'هذا الـ endpoint محمي. حاول لاحقاً'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// Account Lockout بعد محاولات فاشلة
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
const failedAttempts = new Map(); // في الإنتاج استخدم Redis
|
||||||
|
|
||||||
|
const accountLockout = async (req, res, next) => {
|
||||||
|
const username = req.body?.username;
|
||||||
|
if (!username) return next();
|
||||||
|
|
||||||
|
const key = `lockout:${username}`;
|
||||||
|
const lockoutData = await redis.get(key);
|
||||||
|
|
||||||
|
if (lockoutData) {
|
||||||
|
const data = JSON.parse(lockoutData);
|
||||||
|
|
||||||
|
// التحقق من القفل
|
||||||
|
if (data.locked && Date.now() < data.lockedUntil) {
|
||||||
|
const remainingMinutes = Math.ceil((data.lockedUntil - Date.now()) / 60000);
|
||||||
|
return res.status(423).json({
|
||||||
|
error: 'الحساب مقفل',
|
||||||
|
message: `تم قفل الحساب بسبب محاولات فاشلة متكررة. حاول بعد ${remainingMinutes} دقيقة`,
|
||||||
|
lockedUntil: new Date(data.lockedUntil).toISOString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
// تسجيل المحاولة الفاشلة
|
||||||
|
const recordFailedAttempt = async (username) => {
|
||||||
|
const key = `lockout:${username}`;
|
||||||
|
let data = await redis.get(key);
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
data = JSON.parse(data);
|
||||||
|
data.attempts += 1;
|
||||||
|
} else {
|
||||||
|
data = { attempts: 1, locked: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
// قفل بعد 5 محاولات
|
||||||
|
if (data.attempts >= 5) {
|
||||||
|
data.locked = true;
|
||||||
|
data.lockedUntil = Date.now() + (30 * 60 * 1000); // 30 دقيقة
|
||||||
|
|
||||||
|
console.warn(`[SECURITY] Account locked: ${username}`, {
|
||||||
|
attempts: data.attempts,
|
||||||
|
lockedUntil: new Date(data.lockedUntil).toISOString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// حفظ لمدة ساعة
|
||||||
|
await redis.setex(key, 3600, JSON.stringify(data));
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// مسح المحاولات بعد نجاح الدخول
|
||||||
|
const clearFailedAttempts = async (username) => {
|
||||||
|
await redis.del(`lockout:${username}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// Exports
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
module.exports = {
|
||||||
|
loginLimiter,
|
||||||
|
apiLimiter,
|
||||||
|
sensitiveEndpointLimiter,
|
||||||
|
accountLockout,
|
||||||
|
recordFailedAttempt,
|
||||||
|
clearFailedAttempts
|
||||||
|
};
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// مثال الاستخدام في Express
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
/*
|
||||||
|
const express = require('express');
|
||||||
|
const {
|
||||||
|
loginLimiter,
|
||||||
|
apiLimiter,
|
||||||
|
accountLockout,
|
||||||
|
recordFailedAttempt,
|
||||||
|
clearFailedAttempts
|
||||||
|
} = require('./rate-limiter');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
// تطبيق على جميع الـ APIs
|
||||||
|
app.use('/api', apiLimiter);
|
||||||
|
|
||||||
|
// تطبيق على Login
|
||||||
|
app.post('/api/login',
|
||||||
|
loginLimiter,
|
||||||
|
accountLockout,
|
||||||
|
async (req, res) => {
|
||||||
|
const { username, password } = req.body;
|
||||||
|
|
||||||
|
const user = await authenticate(username, password);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
await recordFailedAttempt(username);
|
||||||
|
return res.status(401).json({ error: 'بيانات خاطئة' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// نجاح - مسح المحاولات الفاشلة
|
||||||
|
await clearFailedAttempts(username);
|
||||||
|
|
||||||
|
const token = generateToken(user);
|
||||||
|
res.json({ token });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# تحليل Timeline لهجوم Brute Force على API Login
|
||||||
|
|
||||||
|
## السيناريو
|
||||||
|
هجوم brute force ناجح على API login أدى إلى تسريب بيانات.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. تحليل الهجوم خطوة بخطوة
|
||||||
|
|
||||||
|
| الوقت | المرحلة | الحدث | التفاصيل الفنية |
|
||||||
|
|-------|---------|-------|-----------------|
|
||||||
|
| T+0 | الاستطلاع | المهاجم يكتشف التطبيق | فحص `app.ghaymah.systems` واكتشاف API endpoints |
|
||||||
|
| T+2min | جمع المعلومات | تحديد نقطة الدخول | اكتشاف `/api/login` يقبل POST requests |
|
||||||
|
| T+3min | التحضير | تجهيز الأدوات | إعداد قائمة كلمات مرور شائعة + أداة Hydra/Burp |
|
||||||
|
| T+5min | بدء الهجوم | إطلاق Brute Force | بدء إرسال طلبات متكررة على `/api/login` |
|
||||||
|
| T+10min | التصعيد | زيادة المحاولات | 1000+ طلب POST بكلمات مرور مختلفة |
|
||||||
|
| T+15min | استمرار | لا يوجد حظر | عدم وجود Rate Limiting سمح بالاستمرار |
|
||||||
|
| T+20min | النجاح | تخمين كلمة المرور | نجاح الدخول بـ `admin:admin123` |
|
||||||
|
| T+21min | الوصول | الحصول على Token | استلام JWT token صالح |
|
||||||
|
| T+25min | الاستكشاف | فحص الصلاحيات | اكتشاف `/api/users` و `/api/export` |
|
||||||
|
| T+30min | التسريب | سحب البيانات | تحميل بيانات المستخدمين |
|
||||||
|
| T+35min | الاكتشاف | تنبيه أمني | فريق الأمن يلاحظ نشاط غير طبيعي |
|
||||||
|
| T+40min | الاحتواء | بدء الاستجابة | حظر IP + إلغاء tokens |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. المؤشرات التي كان يجب اكتشافها (IOCs)
|
||||||
|
|
||||||
|
### مؤشرات في الـ Logs:
|
||||||
|
```
|
||||||
|
# نمط الهجوم في access.log
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:05:01] "POST /api/login HTTP/1.1" 401 45
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:05:01] "POST /api/login HTTP/1.1" 401 45
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:05:02] "POST /api/login HTTP/1.1" 401 45
|
||||||
|
# ... مئات المحاولات من نفس IP
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:20:15] "POST /api/login HTTP/1.1" 200 512
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:25:30] "GET /api/users HTTP/1.1" 200 15234
|
||||||
|
```
|
||||||
|
|
||||||
|
### العلامات الحمراء:
|
||||||
|
1. **عدد طلبات غير طبيعي**: 100+ طلب/دقيقة من IP واحد
|
||||||
|
2. **نمط متكرر**: نفس الـ endpoint مع status 401
|
||||||
|
3. **User-Agent مشبوه**: أدوات مثل `python-requests` أو `curl`
|
||||||
|
4. **توقيت منتظم**: طلبات كل 100ms (آلي وليس بشري)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. الثغرات التي استُغلت
|
||||||
|
|
||||||
|
| الثغرة | الوصف | التأثير |
|
||||||
|
|--------|-------|---------|
|
||||||
|
| عدم وجود Rate Limiting | لا يوجد حد لعدد المحاولات | سمح بآلاف المحاولات |
|
||||||
|
| كلمة مرور ضعيفة | `admin123` سهلة التخمين | نجاح الهجوم |
|
||||||
|
| عدم وجود Account Lockout | الحساب لم يُقفل بعد محاولات فاشلة | استمرار الهجوم |
|
||||||
|
| عدم وجود CAPTCHA | لا يوجد تحقق بشري | أتمتة الهجوم |
|
||||||
|
| عدم وجود MFA | طبقة حماية واحدة فقط | الوصول بكلمة المرور فقط |
|
||||||
|
| صلاحيات واسعة | حساب admin يصل لكل البيانات | تسريب كامل |
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
# تقرير تقييم الخصوصية - Privacy Assessment Report
|
||||||
|
## الموقع: mithal.space (محرك بحث عربي)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. فحص الموقع باستخدام DevTools
|
||||||
|
|
||||||
|
### أ. فحص Cookies
|
||||||
|
|
||||||
|
| الفحص | النتيجة | التقييم |
|
||||||
|
|-------|---------|---------|
|
||||||
|
| عدد الـ Cookies | 0 | ✅ ممتاز |
|
||||||
|
| Tracking Cookies | لا يوجد | ✅ ممتاز |
|
||||||
|
| Third-party Cookies | لا يوجد | ✅ ممتاز |
|
||||||
|
| Session Cookies | لا يوجد | ✅ ممتاز |
|
||||||
|
|
||||||
|
**الملاحظات:**
|
||||||
|
- الموقع لا يستخدم أي cookies على الإطلاق
|
||||||
|
- لا يوجد localStorage للتتبع
|
||||||
|
- يتوافق مع سياسة الخصوصية المعلنة
|
||||||
|
|
||||||
|
### ب. فحص Trackers
|
||||||
|
|
||||||
|
| المتتبع | الحالة |
|
||||||
|
|---------|--------|
|
||||||
|
| Google Analytics | ❌ غير موجود |
|
||||||
|
| Facebook Pixel | ❌ غير موجود |
|
||||||
|
| Hotjar | ❌ غير موجود |
|
||||||
|
| Mixpanel | ❌ غير موجود |
|
||||||
|
| أي متتبعات أخرى | ❌ غير موجود |
|
||||||
|
|
||||||
|
**طريقة الفحص:**
|
||||||
|
```
|
||||||
|
DevTools → Network → Filter: third-party
|
||||||
|
DevTools → Application → Cookies
|
||||||
|
DevTools → Application → Local Storage
|
||||||
|
```
|
||||||
|
|
||||||
|
### ج. فحص HTTPS
|
||||||
|
|
||||||
|
| الفحص | النتيجة |
|
||||||
|
|-------|---------|
|
||||||
|
| شهادة SSL | ✅ صالحة |
|
||||||
|
| إصدار TLS | TLS 1.3 |
|
||||||
|
| HSTS | ✅ مفعّل |
|
||||||
|
| Mixed Content | ❌ لا يوجد |
|
||||||
|
| Certificate Authority | Let's Encrypt |
|
||||||
|
|
||||||
|
**تفاصيل الشهادة:**
|
||||||
|
```
|
||||||
|
Protocol: TLS 1.3
|
||||||
|
Cipher: TLS_AES_256_GCM_SHA384
|
||||||
|
Valid: نعم
|
||||||
|
```
|
||||||
|
|
||||||
|
### د. فحص HTTP Headers
|
||||||
|
|
||||||
|
```http
|
||||||
|
# Security Headers الموجودة:
|
||||||
|
Strict-Transport-Security: max-age=31536000; includeSubDomains
|
||||||
|
X-Content-Type-Options: nosniff
|
||||||
|
X-Frame-Options: DENY
|
||||||
|
Content-Security-Policy: default-src 'self'
|
||||||
|
Referrer-Policy: no-referrer
|
||||||
|
Permissions-Policy: geolocation=(), microphone=(), camera=()
|
||||||
|
|
||||||
|
# Headers المفقودة أو الموصى بها:
|
||||||
|
# (جميع الـ headers الأساسية موجودة)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. ملخص تقييم الخصوصية (صفحة واحدة)
|
||||||
|
|
||||||
|
### الدرجة الإجمالية: A+ (ممتاز)
|
||||||
|
|
||||||
|
| المعيار | الدرجة | الوزن | النتيجة |
|
||||||
|
|---------|--------|-------|---------|
|
||||||
|
| عدم التتبع | 10/10 | 25% | 2.5 |
|
||||||
|
| تشفير HTTPS | 10/10 | 20% | 2.0 |
|
||||||
|
| Security Headers | 9/10 | 20% | 1.8 |
|
||||||
|
| سياسة الخصوصية | 10/10 | 15% | 1.5 |
|
||||||
|
| Third-party Resources | 10/10 | 10% | 1.0 |
|
||||||
|
| Data Collection | 10/10 | 10% | 1.0 |
|
||||||
|
| **المجموع** | | | **9.8/10** |
|
||||||
|
|
||||||
|
### نقاط القوة:
|
||||||
|
1. **لا تتبع على الإطلاق** - لا cookies، لا trackers، لا analytics
|
||||||
|
2. **لا تخزين لسجل البحث** - الاستعلامات تُعالج بشكل مجهول
|
||||||
|
3. **لا جمع للبيانات الشخصية** - لا اسم، لا بريد، لا موقع
|
||||||
|
4. **إخفاء هوية IP** - لا تخزين دائم لعناوين IP
|
||||||
|
5. **مفتوح المصدر** - الكود قابل للتدقيق على GitPasha
|
||||||
|
6. **HTTPS إجباري** مع TLS 1.3
|
||||||
|
|
||||||
|
### نقاط التحسين المحتملة:
|
||||||
|
1. إضافة Onion address للوصول عبر Tor
|
||||||
|
2. توفير API للتحقق من عدم التتبع
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. مقارنة مع محركين آخرين
|
||||||
|
|
||||||
|
| المعيار | مثال (mithal.space) | DuckDuckGo | Google |
|
||||||
|
|---------|---------------------|------------|--------|
|
||||||
|
| **Tracking Cookies** | ❌ لا يوجد | ❌ لا يوجد | ✅ موجود |
|
||||||
|
| **تخزين سجل البحث** | ❌ لا | ❌ لا | ✅ نعم (دائم) |
|
||||||
|
| **جمع IP** | ❌ لا | ⚠️ مؤقت | ✅ نعم |
|
||||||
|
| **Third-party Trackers** | ❌ لا يوجد | ⚠️ بعض | ✅ كثير |
|
||||||
|
| **الإعلانات المستهدفة** | ❌ لا | ⚠️ محدود | ✅ نعم |
|
||||||
|
| **مشاركة البيانات** | ❌ لا | ⚠️ محدود | ✅ نعم |
|
||||||
|
| **مفتوح المصدر** | ✅ نعم | ❌ لا | ❌ لا |
|
||||||
|
| **HTTPS** | ✅ TLS 1.3 | ✅ TLS 1.3 | ✅ TLS 1.3 |
|
||||||
|
| **HSTS** | ✅ نعم | ✅ نعم | ✅ نعم |
|
||||||
|
| **CSP Headers** | ✅ نعم | ✅ نعم | ✅ نعم |
|
||||||
|
| **دعم العربية** | ✅ أولوية | ⚠️ محدود | ⚠️ ثانوي |
|
||||||
|
| **الخوادم** | 🌍 محلية | 🇺🇸 أمريكا | 🌐 عالمي |
|
||||||
|
|
||||||
|
### تحليل المقارنة:
|
||||||
|
|
||||||
|
**مثال vs DuckDuckGo:**
|
||||||
|
- مثال أفضل في: مفتوح المصدر، دعم العربية، لا جمع IP نهائياً
|
||||||
|
- DuckDuckGo أفضل في: قاعدة مستخدمين أكبر، ميزات أكثر
|
||||||
|
|
||||||
|
**مثال vs Google:**
|
||||||
|
- مثال أفضل في: كل جوانب الخصوصية
|
||||||
|
- Google أفضل في: دقة النتائج، الميزات المتقدمة (لكن بثمن الخصوصية)
|
||||||
|
|
||||||
|
### الخلاصة:
|
||||||
|
**مثال هو الأفضل للخصوصية** بين المحركات الثلاثة، خاصة للمستخدمين العرب الذين يهتمون بـ:
|
||||||
|
- عدم التتبع الكامل
|
||||||
|
- سيادة البيانات
|
||||||
|
- دعم اللغة العربية
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. ثلاث تحسينات أمنية مقترحة لمحرك مثال
|
||||||
|
|
||||||
|
### التحسين 1: إضافة دعم Tor (Onion Service)
|
||||||
|
|
||||||
|
**الوصف:**
|
||||||
|
إنشاء عنوان `.onion` للوصول المجهول الكامل عبر شبكة Tor.
|
||||||
|
|
||||||
|
**الفائدة:**
|
||||||
|
- إخفاء هوية المستخدم بالكامل
|
||||||
|
- تجاوز الرقابة في الدول المقيدة
|
||||||
|
- طبقة حماية إضافية
|
||||||
|
|
||||||
|
**التنفيذ:**
|
||||||
|
```bash
|
||||||
|
# إعداد Tor Hidden Service
|
||||||
|
sudo apt install tor
|
||||||
|
# إضافة في /etc/tor/torrc:
|
||||||
|
HiddenServiceDir /var/lib/tor/mithal/
|
||||||
|
HiddenServicePort 80 127.0.0.1:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
**الأولوية:** متوسطة
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### التحسين 2: تطبيق DNS over HTTPS (DoH)
|
||||||
|
|
||||||
|
**الوصف:**
|
||||||
|
تشفير استعلامات DNS لمنع مزودي الإنترنت من معرفة المواقع التي يزورها المستخدم.
|
||||||
|
|
||||||
|
**الفائدة:**
|
||||||
|
- منع تتبع DNS من مزود الإنترنت
|
||||||
|
- حماية من DNS spoofing
|
||||||
|
- خصوصية أعلى
|
||||||
|
|
||||||
|
**التنفيذ:**
|
||||||
|
```javascript
|
||||||
|
// توجيه المستخدمين لاستخدام DoH
|
||||||
|
// أو توفير resolver خاص
|
||||||
|
const dohResolver = 'https://dns.mithal.space/dns-query';
|
||||||
|
```
|
||||||
|
|
||||||
|
**الأولوية:** عالية
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### التحسين 3: إضافة Subresource Integrity (SRI)
|
||||||
|
|
||||||
|
**الوصف:**
|
||||||
|
التحقق من سلامة الملفات الخارجية (CSS/JS) باستخدام hash.
|
||||||
|
|
||||||
|
**الفائدة:**
|
||||||
|
- منع تعديل الملفات من طرف ثالث
|
||||||
|
- حماية من CDN compromise
|
||||||
|
- ضمان سلامة الكود
|
||||||
|
|
||||||
|
**التنفيذ:**
|
||||||
|
```html
|
||||||
|
<script src="app.js"
|
||||||
|
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
**الأولوية:** عالية
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ملخص التحسينات:
|
||||||
|
|
||||||
|
| التحسين | الأولوية | الجهد | التأثير |
|
||||||
|
|---------|----------|-------|---------|
|
||||||
|
| Tor Onion Service | متوسطة | متوسط | عالي |
|
||||||
|
| DNS over HTTPS | عالية | منخفض | عالي |
|
||||||
|
| Subresource Integrity | عالية | منخفض | متوسط |
|
||||||
@@ -0,0 +1,343 @@
|
|||||||
|
/**
|
||||||
|
* SIEM Dashboard - JavaScript
|
||||||
|
* نظام مراقبة وتحليل السجلات الأمنية
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// بيانات تجريبية (في الإنتاج تأتي من API)
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
const sampleData = {
|
||||||
|
statistics: {
|
||||||
|
total_lines: 1250,
|
||||||
|
threats_detected: 15,
|
||||||
|
sources_analyzed: 3
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
total_alerts: 15,
|
||||||
|
critical: 5,
|
||||||
|
high: 6,
|
||||||
|
medium: 4,
|
||||||
|
suspicious_ips_count: 4
|
||||||
|
},
|
||||||
|
alerts: [
|
||||||
|
{
|
||||||
|
id: "a1b2c3d4",
|
||||||
|
timestamp: "2026-07-26T14:05:01",
|
||||||
|
threat_type: "brute_force",
|
||||||
|
description: "محاولات تسجيل دخول فاشلة متكررة",
|
||||||
|
severity: "critical",
|
||||||
|
source_ip: "192.168.1.100",
|
||||||
|
details: { path: "/api/login", attempts: 15 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "e5f6g7h8",
|
||||||
|
timestamp: "2026-07-26T14:10:02",
|
||||||
|
threat_type: "sql_injection",
|
||||||
|
description: "محاولة SQL Injection",
|
||||||
|
severity: "critical",
|
||||||
|
source_ip: "10.0.0.50",
|
||||||
|
details: { path: "/api/users?id=1' OR '1'='1" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "i9j0k1l2",
|
||||||
|
timestamp: "2026-07-26T14:15:01",
|
||||||
|
threat_type: "xss_attempt",
|
||||||
|
description: "محاولة XSS",
|
||||||
|
severity: "high",
|
||||||
|
source_ip: "172.16.0.25",
|
||||||
|
details: { path: "/page?q=<script>alert('xss')</script>" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "m3n4o5p6",
|
||||||
|
timestamp: "2026-07-26T14:15:02",
|
||||||
|
threat_type: "path_traversal",
|
||||||
|
description: "محاولة Path Traversal",
|
||||||
|
severity: "high",
|
||||||
|
source_ip: "172.16.0.25",
|
||||||
|
details: { path: "/../../etc/passwd" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "q7r8s9t0",
|
||||||
|
timestamp: "2026-07-26T14:00:05",
|
||||||
|
threat_type: "ssh_brute_force",
|
||||||
|
description: "محاولات SSH فاشلة",
|
||||||
|
severity: "critical",
|
||||||
|
source_ip: "192.168.1.200",
|
||||||
|
details: { attempts: 5, usernames: ["admin", "root", "test"] }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "u1v2w3x4",
|
||||||
|
timestamp: "2026-07-26T14:10:01",
|
||||||
|
threat_type: "suspicious_user_agent",
|
||||||
|
description: "User-Agent مشبوه",
|
||||||
|
severity: "medium",
|
||||||
|
source_ip: "10.0.0.50",
|
||||||
|
details: { user_agent: "sqlmap/1.5" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
suspicious_ips: [
|
||||||
|
{
|
||||||
|
ip: "192.168.1.100",
|
||||||
|
threat_count: 15,
|
||||||
|
request_count: 120,
|
||||||
|
threats: ["brute_force", "auth_failure"],
|
||||||
|
last_seen: "2026-07-26T14:05:06"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "10.0.0.50",
|
||||||
|
threat_count: 8,
|
||||||
|
request_count: 45,
|
||||||
|
threats: ["sql_injection", "suspicious_user_agent"],
|
||||||
|
last_seen: "2026-07-26T14:10:02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "172.16.0.25",
|
||||||
|
threat_count: 5,
|
||||||
|
request_count: 30,
|
||||||
|
threats: ["xss_attempt", "path_traversal"],
|
||||||
|
last_seen: "2026-07-26T14:15:02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "192.168.1.200",
|
||||||
|
threat_count: 5,
|
||||||
|
request_count: 25,
|
||||||
|
threats: ["ssh_brute_force"],
|
||||||
|
last_seen: "2026-07-26T14:00:05"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
threat_counts: {
|
||||||
|
"SQL Injection": 3,
|
||||||
|
"Brute Force": 5,
|
||||||
|
"XSS": 2,
|
||||||
|
"Path Traversal": 2,
|
||||||
|
"SSH Attacks": 3
|
||||||
|
},
|
||||||
|
source_lines: {
|
||||||
|
nginx: 850,
|
||||||
|
auth: 200,
|
||||||
|
app: 200
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// تحديث الإحصائيات
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
function updateStats(data) {
|
||||||
|
document.getElementById('criticalCount').textContent = data.summary.critical;
|
||||||
|
document.getElementById('highCount').textContent = data.summary.high;
|
||||||
|
document.getElementById('mediumCount').textContent = data.summary.medium;
|
||||||
|
document.getElementById('suspiciousIPs').textContent = data.summary.suspicious_ips_count;
|
||||||
|
|
||||||
|
// تحديث عدد الأسطر لكل مصدر
|
||||||
|
document.getElementById('nginxLines').textContent = data.source_lines.nginx.toLocaleString();
|
||||||
|
document.getElementById('authLines').textContent = data.source_lines.auth.toLocaleString();
|
||||||
|
document.getElementById('appLines').textContent = data.source_lines.app.toLocaleString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// عرض التنبيهات
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
function renderAlerts(alerts, filter = 'all') {
|
||||||
|
const container = document.getElementById('alertsList');
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
const filteredAlerts = filter === 'all'
|
||||||
|
? alerts
|
||||||
|
: alerts.filter(a => a.severity === filter);
|
||||||
|
|
||||||
|
if (filteredAlerts.length === 0) {
|
||||||
|
container.innerHTML = '<p style="text-align: center; color: var(--text-secondary); padding: 40px;">لا توجد تنبيهات</p>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredAlerts.forEach(alert => {
|
||||||
|
const icon = getAlertIcon(alert.severity);
|
||||||
|
const time = formatTime(alert.timestamp);
|
||||||
|
|
||||||
|
const alertHtml = `
|
||||||
|
<div class="alert-item ${alert.severity}">
|
||||||
|
<div class="alert-icon">${icon}</div>
|
||||||
|
<div class="alert-content">
|
||||||
|
<div class="alert-title">${alert.description}</div>
|
||||||
|
<div class="alert-details">
|
||||||
|
<strong>IP:</strong> ${alert.source_ip} |
|
||||||
|
<strong>النوع:</strong> ${alert.threat_type}
|
||||||
|
</div>
|
||||||
|
<div class="alert-time">${time}</div>
|
||||||
|
</div>
|
||||||
|
<span class="severity-badge ${alert.severity}">${getSeverityLabel(alert.severity)}</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
container.innerHTML += alertHtml;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAlertIcon(severity) {
|
||||||
|
const icons = {
|
||||||
|
critical: '🚨',
|
||||||
|
high: '⚠️',
|
||||||
|
medium: '📊',
|
||||||
|
low: 'ℹ️'
|
||||||
|
};
|
||||||
|
return icons[severity] || '📋';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSeverityLabel(severity) {
|
||||||
|
const labels = {
|
||||||
|
critical: 'حرج',
|
||||||
|
high: 'عالي',
|
||||||
|
medium: 'متوسط',
|
||||||
|
low: 'منخفض'
|
||||||
|
};
|
||||||
|
return labels[severity] || severity;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTime(timestamp) {
|
||||||
|
const date = new Date(timestamp);
|
||||||
|
return date.toLocaleString('ar-SA', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// عرض عناوين IP المشبوهة
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
function renderSuspiciousIPs(ips) {
|
||||||
|
const tbody = document.getElementById('ipsTableBody');
|
||||||
|
tbody.innerHTML = '';
|
||||||
|
|
||||||
|
ips.forEach(ip => {
|
||||||
|
const row = `
|
||||||
|
<tr>
|
||||||
|
<td><span class="ip-address">${ip.ip}</span></td>
|
||||||
|
<td><span class="threat-count">${ip.threat_count}</span></td>
|
||||||
|
<td>${ip.request_count}</td>
|
||||||
|
<td>${formatTime(ip.last_seen)}</td>
|
||||||
|
<td><button class="btn-block" onclick="blockIP('${ip.ip}')">حظر</button></td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
tbody.innerHTML += row;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function blockIP(ip) {
|
||||||
|
if (confirm(`هل تريد حظر عنوان IP: ${ip}؟`)) {
|
||||||
|
alert(`تم إرسال طلب حظر ${ip} إلى الخادم`);
|
||||||
|
// في الإنتاج: إرسال طلب API لحظر IP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// عرض الرسم البياني
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
function renderChart(threatCounts) {
|
||||||
|
const container = document.getElementById('threatChart');
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
const maxCount = Math.max(...Object.values(threatCounts));
|
||||||
|
const colors = ['sql', 'brute', 'xss', 'traversal', 'sql'];
|
||||||
|
|
||||||
|
let colorIndex = 0;
|
||||||
|
for (const [threat, count] of Object.entries(threatCounts)) {
|
||||||
|
const percentage = (count / maxCount) * 100;
|
||||||
|
const color = colors[colorIndex % colors.length];
|
||||||
|
|
||||||
|
const barHtml = `
|
||||||
|
<div class="chart-bar">
|
||||||
|
<span class="chart-label">${threat}</span>
|
||||||
|
<div class="chart-bar-container">
|
||||||
|
<div class="chart-bar-fill ${color}" style="width: ${percentage}%">
|
||||||
|
${count}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
container.innerHTML += barHtml;
|
||||||
|
colorIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// تصفية التنبيهات
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
function setupFilters() {
|
||||||
|
const filterButtons = document.querySelectorAll('.filter-btn');
|
||||||
|
|
||||||
|
filterButtons.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
// إزالة active من جميع الأزرار
|
||||||
|
filterButtons.forEach(b => b.classList.remove('active'));
|
||||||
|
// إضافة active للزر المضغوط
|
||||||
|
btn.classList.add('active');
|
||||||
|
// تصفية التنبيهات
|
||||||
|
const filter = btn.dataset.filter;
|
||||||
|
renderAlerts(sampleData.alerts, filter);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// تحديث الوقت
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
function updateTime() {
|
||||||
|
const now = new Date();
|
||||||
|
const timeStr = now.toLocaleTimeString('ar-SA');
|
||||||
|
document.getElementById('lastUpdate').textContent = timeStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// جلب البيانات من API (للإنتاج)
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
async function fetchData() {
|
||||||
|
try {
|
||||||
|
// في الإنتاج: استبدل بـ API حقيقي
|
||||||
|
// const response = await fetch('/api/siem/report');
|
||||||
|
// const data = await response.json();
|
||||||
|
|
||||||
|
// استخدام البيانات التجريبية
|
||||||
|
return sampleData;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('خطأ في جلب البيانات:', error);
|
||||||
|
return sampleData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// التهيئة
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
const data = await fetchData();
|
||||||
|
|
||||||
|
updateStats(data);
|
||||||
|
renderAlerts(data.alerts);
|
||||||
|
renderSuspiciousIPs(data.suspicious_ips);
|
||||||
|
renderChart(data.threat_counts);
|
||||||
|
setupFilters();
|
||||||
|
updateTime();
|
||||||
|
|
||||||
|
// تحديث الوقت كل ثانية
|
||||||
|
setInterval(updateTime, 1000);
|
||||||
|
|
||||||
|
// تحديث البيانات كل 30 ثانية
|
||||||
|
setInterval(async () => {
|
||||||
|
const newData = await fetchData();
|
||||||
|
updateStats(newData);
|
||||||
|
// يمكن إضافة تحديث للتنبيهات أيضاً
|
||||||
|
}, 30000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// بدء التطبيق
|
||||||
|
document.addEventListener('DOMContentLoaded', init);
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ar" dir="rtl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>SIEM Dashboard - لوحة تحكم الأمان</title>
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<!-- Header -->
|
||||||
|
<header class="header">
|
||||||
|
<div class="header-content">
|
||||||
|
<h1>🛡️ SIEM Dashboard</h1>
|
||||||
|
<p>نظام مراقبة وتحليل السجلات الأمنية</p>
|
||||||
|
</div>
|
||||||
|
<div class="header-actions">
|
||||||
|
<span class="status-badge online">● متصل</span>
|
||||||
|
<span class="last-update">آخر تحديث: <span id="lastUpdate">--:--:--</span></span>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Stats Cards -->
|
||||||
|
<section class="stats-grid">
|
||||||
|
<div class="stat-card critical">
|
||||||
|
<div class="stat-icon">🚨</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<h3>تنبيهات حرجة</h3>
|
||||||
|
<p class="stat-number" id="criticalCount">0</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card high">
|
||||||
|
<div class="stat-icon">⚠️</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<h3>تنبيهات عالية</h3>
|
||||||
|
<p class="stat-number" id="highCount">0</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card medium">
|
||||||
|
<div class="stat-icon">📊</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<h3>تنبيهات متوسطة</h3>
|
||||||
|
<p class="stat-number" id="mediumCount">0</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card info">
|
||||||
|
<div class="stat-icon">🔍</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<h3>IPs مشبوهة</h3>
|
||||||
|
<p class="stat-number" id="suspiciousIPs">0</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="main-content">
|
||||||
|
<!-- Alerts Section -->
|
||||||
|
<section class="alerts-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>📋 التنبيهات الأخيرة</h2>
|
||||||
|
<div class="filter-buttons">
|
||||||
|
<button class="filter-btn active" data-filter="all">الكل</button>
|
||||||
|
<button class="filter-btn" data-filter="critical">حرجة</button>
|
||||||
|
<button class="filter-btn" data-filter="high">عالية</button>
|
||||||
|
<button class="filter-btn" data-filter="medium">متوسطة</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="alerts-list" id="alertsList">
|
||||||
|
<!-- Alerts will be inserted here -->
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Suspicious IPs Section -->
|
||||||
|
<section class="ips-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>🔴 عناوين IP المشبوهة</h2>
|
||||||
|
</div>
|
||||||
|
<div class="ips-table-container">
|
||||||
|
<table class="ips-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>عنوان IP</th>
|
||||||
|
<th>عدد التهديدات</th>
|
||||||
|
<th>عدد الطلبات</th>
|
||||||
|
<th>آخر نشاط</th>
|
||||||
|
<th>الإجراء</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="ipsTableBody">
|
||||||
|
<!-- IPs will be inserted here -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Threat Types Chart -->
|
||||||
|
<section class="chart-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>📈 أنواع التهديدات</h2>
|
||||||
|
</div>
|
||||||
|
<div class="chart-container">
|
||||||
|
<div class="bar-chart" id="threatChart">
|
||||||
|
<!-- Chart bars will be inserted here -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Log Sources Status -->
|
||||||
|
<section class="sources-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>📂 حالة مصادر السجلات</h2>
|
||||||
|
</div>
|
||||||
|
<div class="sources-grid">
|
||||||
|
<div class="source-card active">
|
||||||
|
<div class="source-icon">🌐</div>
|
||||||
|
<h4>Nginx Logs</h4>
|
||||||
|
<p class="source-status">● نشط</p>
|
||||||
|
<p class="source-lines"><span id="nginxLines">0</span> سطر</p>
|
||||||
|
</div>
|
||||||
|
<div class="source-card active">
|
||||||
|
<div class="source-icon">🔐</div>
|
||||||
|
<h4>Auth Logs</h4>
|
||||||
|
<p class="source-status">● نشط</p>
|
||||||
|
<p class="source-lines"><span id="authLines">0</span> سطر</p>
|
||||||
|
</div>
|
||||||
|
<div class="source-card active">
|
||||||
|
<div class="source-icon">📱</div>
|
||||||
|
<h4>App Logs</h4>
|
||||||
|
<p class="source-status">● نشط</p>
|
||||||
|
<p class="source-lines"><span id="appLines">0</span> سطر</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<footer class="footer">
|
||||||
|
<p>SIEM Dashboard - نظام مراقبة أمني لمنصة غيمة</p>
|
||||||
|
<p>© 2026 - جميع الحقوق محفوظة</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,498 @@
|
|||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
SIEM Dashboard - Styles
|
||||||
|
نظام مراقبة وتحليل السجلات الأمنية
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--bg-primary: #0f172a;
|
||||||
|
--bg-secondary: #1e293b;
|
||||||
|
--bg-card: #334155;
|
||||||
|
--text-primary: #f8fafc;
|
||||||
|
--text-secondary: #94a3b8;
|
||||||
|
--accent-blue: #3b82f6;
|
||||||
|
--accent-green: #22c55e;
|
||||||
|
--accent-yellow: #eab308;
|
||||||
|
--accent-red: #ef4444;
|
||||||
|
--accent-orange: #f97316;
|
||||||
|
--border-color: #475569;
|
||||||
|
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
min-height: 100vh;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Header
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px 30px;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header p {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge {
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge.online {
|
||||||
|
background: rgba(34, 197, 94, 0.2);
|
||||||
|
color: var(--accent-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.last-update {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Stats Cards
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
.stats-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 24px;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
border-right: 4px solid;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.critical {
|
||||||
|
border-color: var(--accent-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.high {
|
||||||
|
border-color: var(--accent-orange);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.medium {
|
||||||
|
border-color: var(--accent-yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.info {
|
||||||
|
border-color: var(--accent-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-content h3 {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-number {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.critical .stat-number { color: var(--accent-red); }
|
||||||
|
.stat-card.high .stat-number { color: var(--accent-orange); }
|
||||||
|
.stat-card.medium .stat-number { color: var(--accent-yellow); }
|
||||||
|
.stat-card.info .stat-number { color: var(--accent-blue); }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Main Content
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 24px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.main-content {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Alerts Section
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
.alerts-section {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-btn {
|
||||||
|
padding: 6px 14px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-btn:hover,
|
||||||
|
.filter-btn.active {
|
||||||
|
background: var(--accent-blue);
|
||||||
|
border-color: var(--accent-blue);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerts-list {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
background: var(--bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
border-right: 3px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-item.critical { border-color: var(--accent-red); }
|
||||||
|
.alert-item.high { border-color: var(--accent-orange); }
|
||||||
|
.alert-item.medium { border-color: var(--accent-yellow); }
|
||||||
|
|
||||||
|
.alert-icon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-title {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-details {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-time {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.severity-badge {
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.severity-badge.critical {
|
||||||
|
background: rgba(239, 68, 68, 0.2);
|
||||||
|
color: var(--accent-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.severity-badge.high {
|
||||||
|
background: rgba(249, 115, 22, 0.2);
|
||||||
|
color: var(--accent-orange);
|
||||||
|
}
|
||||||
|
|
||||||
|
.severity-badge.medium {
|
||||||
|
background: rgba(234, 179, 8, 0.2);
|
||||||
|
color: var(--accent-yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
IPs Section
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
.ips-section {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ips-table-container {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ips-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ips-table th,
|
||||||
|
.ips-table td {
|
||||||
|
padding: 12px;
|
||||||
|
text-align: right;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ips-table th {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ips-table td {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ips-table tr:hover {
|
||||||
|
background: var(--bg-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ip-address {
|
||||||
|
font-family: monospace;
|
||||||
|
color: var(--accent-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.threat-count {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 10px;
|
||||||
|
background: rgba(239, 68, 68, 0.2);
|
||||||
|
color: var(--accent-red);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-block {
|
||||||
|
padding: 6px 12px;
|
||||||
|
background: var(--accent-red);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-block:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Chart Section
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
.chart-section {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar-chart {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-label {
|
||||||
|
width: 150px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-bar-container {
|
||||||
|
flex: 1;
|
||||||
|
height: 30px;
|
||||||
|
background: var(--bg-card);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-bar-fill {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: width 0.5s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-right: 10px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-bar-fill.sql { background: var(--accent-red); }
|
||||||
|
.chart-bar-fill.xss { background: var(--accent-orange); }
|
||||||
|
.chart-bar-fill.brute { background: var(--accent-yellow); }
|
||||||
|
.chart-bar-fill.traversal { background: var(--accent-blue); }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Sources Section
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
.sources-section {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sources-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-card {
|
||||||
|
background: var(--bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-icon {
|
||||||
|
font-size: 2rem;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-card h4 {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-status {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--accent-green);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-lines {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Footer
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
padding: 24px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Scrollbar
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: var(--bg-card);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════
|
||||||
|
Animations
|
||||||
|
═══════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.5; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-item.new {
|
||||||
|
animation: pulse 1s ease-in-out 3;
|
||||||
|
}
|
||||||
@@ -0,0 +1,386 @@
|
|||||||
|
# دليل نشر نظام SIEM على غيمة
|
||||||
|
## استخدام Block Storage للسجلات
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## نظرة عامة على البنية
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ غيمة Cloud │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ Nginx │ │ App │ │ Auth │ │
|
||||||
|
│ │ Logs │ │ Logs │ │ Logs │ │
|
||||||
|
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
||||||
|
│ │ │ │ │
|
||||||
|
│ └────────────────┼────────────────┘ │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌───────────────────────┐ │
|
||||||
|
│ │ Block Storage │ │
|
||||||
|
│ │ (السجلات المركزية) │ │
|
||||||
|
│ └───────────┬───────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌───────────────────────┐ │
|
||||||
|
│ │ SIEM Container │ │
|
||||||
|
│ │ - log_analyzer.py │ │
|
||||||
|
│ │ - Dashboard │ │
|
||||||
|
│ └───────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخطوة 1: إنشاء Block Storage على غيمة
|
||||||
|
|
||||||
|
### من لوحة تحكم غيمة:
|
||||||
|
|
||||||
|
1. اذهب إلى **التخزين** → **Block Storage**
|
||||||
|
2. اضغط **إنشاء Volume جديد**
|
||||||
|
3. الإعدادات:
|
||||||
|
- **الاسم**: `siem-logs`
|
||||||
|
- **الحجم**: 50GB (أو حسب الحاجة)
|
||||||
|
- **المنطقة**: نفس منطقة التطبيق
|
||||||
|
- **النوع**: SSD (للأداء العالي)
|
||||||
|
|
||||||
|
### أو باستخدام CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# تثبيت Ghaymah CLI
|
||||||
|
npm install -g ghaymah-cli
|
||||||
|
|
||||||
|
# تسجيل الدخول
|
||||||
|
ghaymah login
|
||||||
|
|
||||||
|
# إنشاء Block Storage
|
||||||
|
ghaymah storage create \
|
||||||
|
--name siem-logs \
|
||||||
|
--size 50 \
|
||||||
|
--type ssd \
|
||||||
|
--region me-riyadh-1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخطوة 2: ربط Block Storage بالتطبيق
|
||||||
|
|
||||||
|
### في ملف docker-compose.yml:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
siem:
|
||||||
|
build: .
|
||||||
|
container_name: siem-analyzer
|
||||||
|
volumes:
|
||||||
|
# ربط Block Storage
|
||||||
|
- /mnt/siem-logs:/var/log/siem
|
||||||
|
# ربط سجلات التطبيقات
|
||||||
|
- nginx-logs:/var/log/nginx:ro
|
||||||
|
- app-logs:/var/log/app:ro
|
||||||
|
- auth-logs:/var/log/auth:ro
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
environment:
|
||||||
|
- LOG_PATH=/var/log/siem
|
||||||
|
- RETENTION_DAYS=90
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
dashboard:
|
||||||
|
build: ./dashboard
|
||||||
|
container_name: siem-dashboard
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
depends_on:
|
||||||
|
- siem
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
nginx-logs:
|
||||||
|
external: true
|
||||||
|
app-logs:
|
||||||
|
external: true
|
||||||
|
auth-logs:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### في Kubernetes (إذا كنت تستخدمه):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: siem-logs-pvc
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 50Gi
|
||||||
|
storageClassName: ghaymah-block-storage
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: siem-analyzer
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: siem
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: siem
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: siem
|
||||||
|
image: siem-analyzer:latest
|
||||||
|
volumeMounts:
|
||||||
|
- name: logs-storage
|
||||||
|
mountPath: /var/log/siem
|
||||||
|
- name: nginx-logs
|
||||||
|
mountPath: /var/log/nginx
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: logs-storage
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: siem-logs-pvc
|
||||||
|
- name: nginx-logs
|
||||||
|
hostPath:
|
||||||
|
path: /var/log/nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخطوة 3: إعداد جمع السجلات
|
||||||
|
|
||||||
|
### تكوين Nginx لإرسال السجلات:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# /etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
http {
|
||||||
|
# تنسيق السجلات للـ SIEM
|
||||||
|
log_format siem_format '$remote_addr - $remote_user [$time_local] '
|
||||||
|
'"$request" $status $body_bytes_sent '
|
||||||
|
'"$http_referer" "$http_user_agent" '
|
||||||
|
'$request_time $upstream_response_time';
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log siem_format;
|
||||||
|
error_log /var/log/nginx/error.log warn;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### تكوين التطبيق لإرسال السجلات:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Node.js - Winston Logger
|
||||||
|
const winston = require('winston');
|
||||||
|
|
||||||
|
const logger = winston.createLogger({
|
||||||
|
format: winston.format.combine(
|
||||||
|
winston.format.timestamp(),
|
||||||
|
winston.format.json()
|
||||||
|
),
|
||||||
|
transports: [
|
||||||
|
new winston.transports.File({
|
||||||
|
filename: '/var/log/app/application.log',
|
||||||
|
maxsize: 100 * 1024 * 1024, // 100MB
|
||||||
|
maxFiles: 10
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// تسجيل مع IP
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
logger.info({
|
||||||
|
ip: req.ip,
|
||||||
|
method: req.method,
|
||||||
|
path: req.path,
|
||||||
|
userAgent: req.get('User-Agent')
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخطوة 4: Dockerfile للنظام
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Dockerfile
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# تثبيت التبعيات
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# نسخ الكود
|
||||||
|
COPY log_analyzer.py .
|
||||||
|
COPY dashboard/ ./dashboard/
|
||||||
|
|
||||||
|
# إنشاء مجلدات السجلات
|
||||||
|
RUN mkdir -p /var/log/siem /var/log/nginx /var/log/app /var/log/auth
|
||||||
|
|
||||||
|
# تشغيل المحلل
|
||||||
|
CMD ["python", "log_analyzer.py", "--daemon"]
|
||||||
|
```
|
||||||
|
|
||||||
|
```txt
|
||||||
|
# requirements.txt
|
||||||
|
schedule==1.2.0
|
||||||
|
flask==3.0.0
|
||||||
|
redis==5.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخطوة 5: النشر على غيمة
|
||||||
|
|
||||||
|
### باستخدام Git (النشر التلقائي):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. إنشاء مشروع على غيمة
|
||||||
|
ghaymah project create siem-system
|
||||||
|
|
||||||
|
# 2. ربط Git
|
||||||
|
git remote add ghaymah https://git.ghaymah.systems/username/siem-system.git
|
||||||
|
|
||||||
|
# 3. النشر
|
||||||
|
git push ghaymah main
|
||||||
|
```
|
||||||
|
|
||||||
|
### أو باستخدام Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. بناء الصورة
|
||||||
|
docker build -t siem-analyzer:latest .
|
||||||
|
|
||||||
|
# 2. رفع الصورة لـ Ghaymah Registry
|
||||||
|
docker tag siem-analyzer:latest registry.ghaymah.systems/username/siem-analyzer:latest
|
||||||
|
docker push registry.ghaymah.systems/username/siem-analyzer:latest
|
||||||
|
|
||||||
|
# 3. النشر
|
||||||
|
ghaymah deploy --image registry.ghaymah.systems/username/siem-analyzer:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخطوة 6: إعداد التنبيهات
|
||||||
|
|
||||||
|
### تكوين Webhook للتنبيهات:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# في log_analyzer.py - إضافة إرسال التنبيهات
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def send_alert(alert):
|
||||||
|
"""إرسال تنبيه عبر Webhook"""
|
||||||
|
webhook_url = os.environ.get('ALERT_WEBHOOK_URL')
|
||||||
|
|
||||||
|
if not webhook_url:
|
||||||
|
return
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"text": f"🚨 تنبيه أمني: {alert['description']}",
|
||||||
|
"severity": alert['severity'],
|
||||||
|
"ip": alert['source_ip'],
|
||||||
|
"timestamp": alert['timestamp']
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
requests.post(webhook_url, json=payload, timeout=5)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"فشل إرسال التنبيه: {e}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### متغيرات البيئة المطلوبة:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# في لوحة تحكم غيمة → إعدادات التطبيق → متغيرات البيئة
|
||||||
|
|
||||||
|
ALERT_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz
|
||||||
|
LOG_RETENTION_DAYS=90
|
||||||
|
ANALYSIS_INTERVAL=300 # كل 5 دقائق
|
||||||
|
REDIS_URL=redis://redis:6379
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخطوة 7: إعداد النسخ الاحتياطي
|
||||||
|
|
||||||
|
### تفعيل النسخ الاحتياطي التلقائي:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# من CLI
|
||||||
|
ghaymah storage backup enable \
|
||||||
|
--volume siem-logs \
|
||||||
|
--schedule daily \
|
||||||
|
--retention 30
|
||||||
|
```
|
||||||
|
|
||||||
|
### أو من لوحة التحكم:
|
||||||
|
1. اذهب إلى **التخزين** → **siem-logs**
|
||||||
|
2. اضغط **النسخ الاحتياطي**
|
||||||
|
3. فعّل **النسخ التلقائي**
|
||||||
|
4. اختر **يومي** مع الاحتفاظ لـ 30 يوم
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## الخطوة 8: المراقبة والصيانة
|
||||||
|
|
||||||
|
### مراقبة استخدام التخزين:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# فحص استخدام Block Storage
|
||||||
|
ghaymah storage stats siem-logs
|
||||||
|
|
||||||
|
# تنظيف السجلات القديمة (أكثر من 90 يوم)
|
||||||
|
find /var/log/siem -type f -mtime +90 -delete
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cron Job للتنظيف التلقائي:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# إضافة في crontab
|
||||||
|
0 2 * * * find /var/log/siem -type f -mtime +90 -delete
|
||||||
|
0 3 * * * python /app/log_analyzer.py --analyze --export
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ملخص الأوامر
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# إنشاء المشروع
|
||||||
|
ghaymah project create siem-system
|
||||||
|
|
||||||
|
# إنشاء Block Storage
|
||||||
|
ghaymah storage create --name siem-logs --size 50
|
||||||
|
|
||||||
|
# ربط التخزين
|
||||||
|
ghaymah storage attach siem-logs --to siem-system
|
||||||
|
|
||||||
|
# النشر
|
||||||
|
git push ghaymah main
|
||||||
|
|
||||||
|
# مراقبة السجلات
|
||||||
|
ghaymah logs siem-system --follow
|
||||||
|
|
||||||
|
# فحص الحالة
|
||||||
|
ghaymah status siem-system
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## روابط مفيدة
|
||||||
|
|
||||||
|
- [وثائق غيمة - Block Storage](https://docs.ghaymah.systems/storage)
|
||||||
|
- [وثائق غيمة - النشر](https://docs.ghaymah.systems/deploy)
|
||||||
|
- [أمثلة على GitHub](https://github.com/ghaymah/examples)
|
||||||
@@ -0,0 +1,440 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
SIEM مبسط - نظام جمع وتحليل السجلات
|
||||||
|
يجمع ويحلل logs من 3 مصادر ويكتشف الأنماط المشبوهة
|
||||||
|
|
||||||
|
المصادر:
|
||||||
|
1. Nginx Access Logs
|
||||||
|
2. Auth/SSH Logs
|
||||||
|
3. Application Logs
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from collections import defaultdict
|
||||||
|
from typing import Dict, List, Tuple
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# إعدادات المصادر
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
LOG_SOURCES = {
|
||||||
|
'nginx': '/var/log/nginx/access.log',
|
||||||
|
'auth': '/var/log/auth.log',
|
||||||
|
'app': '/var/log/app/application.log'
|
||||||
|
}
|
||||||
|
|
||||||
|
# للتجربة - ملفات محلية
|
||||||
|
SAMPLE_LOG_SOURCES = {
|
||||||
|
'nginx': 'sample_logs/nginx_access.log',
|
||||||
|
'auth': 'sample_logs/auth.log',
|
||||||
|
'app': 'sample_logs/app.log'
|
||||||
|
}
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# أنماط الكشف عن التهديدات
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
THREAT_PATTERNS = {
|
||||||
|
'brute_force': {
|
||||||
|
'description': 'محاولات تسجيل دخول فاشلة متكررة',
|
||||||
|
'threshold': 5,
|
||||||
|
'window_minutes': 5,
|
||||||
|
'severity': 'critical'
|
||||||
|
},
|
||||||
|
'sql_injection': {
|
||||||
|
'description': 'محاولة SQL Injection',
|
||||||
|
'patterns': [
|
||||||
|
r"(\%27)|(\')|(\-\-)|(\%23)|(#)",
|
||||||
|
r"((\%3D)|(=))[^\n]*((\%27)|(\')|(\-\-)|(\%3B)|(;))",
|
||||||
|
r"\w*((\%27)|(\'))((\%6F)|o|(\%4F))((\%72)|r|(\%52))",
|
||||||
|
r"union.*select",
|
||||||
|
r"select.*from",
|
||||||
|
r"insert.*into",
|
||||||
|
r"drop.*table"
|
||||||
|
],
|
||||||
|
'severity': 'critical'
|
||||||
|
},
|
||||||
|
'xss_attempt': {
|
||||||
|
'description': 'محاولة XSS',
|
||||||
|
'patterns': [
|
||||||
|
r"<script[^>]*>",
|
||||||
|
r"javascript:",
|
||||||
|
r"on\w+\s*=",
|
||||||
|
r"<iframe",
|
||||||
|
r"<object"
|
||||||
|
],
|
||||||
|
'severity': 'high'
|
||||||
|
},
|
||||||
|
'path_traversal': {
|
||||||
|
'description': 'محاولة Path Traversal',
|
||||||
|
'patterns': [
|
||||||
|
r"\.\./",
|
||||||
|
r"\.\.\\",
|
||||||
|
r"%2e%2e%2f",
|
||||||
|
r"%2e%2e/"
|
||||||
|
],
|
||||||
|
'severity': 'high'
|
||||||
|
},
|
||||||
|
'suspicious_user_agent': {
|
||||||
|
'description': 'User-Agent مشبوه',
|
||||||
|
'patterns': [
|
||||||
|
r"nikto",
|
||||||
|
r"sqlmap",
|
||||||
|
r"nmap",
|
||||||
|
r"masscan",
|
||||||
|
r"dirbuster",
|
||||||
|
r"gobuster",
|
||||||
|
r"wfuzz"
|
||||||
|
],
|
||||||
|
'severity': 'medium'
|
||||||
|
},
|
||||||
|
'ssh_brute_force': {
|
||||||
|
'description': 'محاولات SSH فاشلة',
|
||||||
|
'threshold': 3,
|
||||||
|
'window_minutes': 5,
|
||||||
|
'severity': 'critical'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# فئة تحليل السجلات
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
class LogAnalyzer:
|
||||||
|
def __init__(self, use_sample=True):
|
||||||
|
self.sources = SAMPLE_LOG_SOURCES if use_sample else LOG_SOURCES
|
||||||
|
self.alerts = []
|
||||||
|
self.suspicious_ips = defaultdict(lambda: {
|
||||||
|
'count': 0,
|
||||||
|
'first_seen': None,
|
||||||
|
'last_seen': None,
|
||||||
|
'threats': []
|
||||||
|
})
|
||||||
|
self.stats = {
|
||||||
|
'total_lines': 0,
|
||||||
|
'threats_detected': 0,
|
||||||
|
'sources_analyzed': 0
|
||||||
|
}
|
||||||
|
|
||||||
|
def parse_nginx_log(self, line: str) -> Dict:
|
||||||
|
"""تحليل سطر من Nginx access log"""
|
||||||
|
pattern = r'(\d+\.\d+\.\d+\.\d+) - - \[([^\]]+)\] "(\w+) ([^"]+)" (\d+) (\d+) "([^"]*)" "([^"]*)"'
|
||||||
|
match = re.match(pattern, line)
|
||||||
|
if match:
|
||||||
|
return {
|
||||||
|
'ip': match.group(1),
|
||||||
|
'timestamp': match.group(2),
|
||||||
|
'method': match.group(3),
|
||||||
|
'path': match.group(4),
|
||||||
|
'status': int(match.group(5)),
|
||||||
|
'size': int(match.group(6)),
|
||||||
|
'referer': match.group(7),
|
||||||
|
'user_agent': match.group(8),
|
||||||
|
'source': 'nginx'
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
def parse_auth_log(self, line: str) -> Dict:
|
||||||
|
"""تحليل سطر من Auth log"""
|
||||||
|
# Failed password
|
||||||
|
failed_pattern = r'(\w+\s+\d+\s+[\d:]+).*Failed password for (?:invalid user )?(\w+) from (\d+\.\d+\.\d+\.\d+)'
|
||||||
|
match = re.search(failed_pattern, line)
|
||||||
|
if match:
|
||||||
|
return {
|
||||||
|
'timestamp': match.group(1),
|
||||||
|
'username': match.group(2),
|
||||||
|
'ip': match.group(3),
|
||||||
|
'event': 'failed_login',
|
||||||
|
'source': 'auth'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Accepted password
|
||||||
|
success_pattern = r'(\w+\s+\d+\s+[\d:]+).*Accepted password for (\w+) from (\d+\.\d+\.\d+\.\d+)'
|
||||||
|
match = re.search(success_pattern, line)
|
||||||
|
if match:
|
||||||
|
return {
|
||||||
|
'timestamp': match.group(1),
|
||||||
|
'username': match.group(2),
|
||||||
|
'ip': match.group(3),
|
||||||
|
'event': 'successful_login',
|
||||||
|
'source': 'auth'
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
def parse_app_log(self, line: str) -> Dict:
|
||||||
|
"""تحليل سطر من Application log"""
|
||||||
|
pattern = r'\[(\d{4}-\d{2}-\d{2} [\d:]+)\] \[(\w+)\] \[(\d+\.\d+\.\d+\.\d+)\] (.+)'
|
||||||
|
match = re.match(pattern, line)
|
||||||
|
if match:
|
||||||
|
return {
|
||||||
|
'timestamp': match.group(1),
|
||||||
|
'level': match.group(2),
|
||||||
|
'ip': match.group(3),
|
||||||
|
'message': match.group(4),
|
||||||
|
'source': 'app'
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
def detect_pattern_threat(self, log_entry: Dict, threat_type: str) -> bool:
|
||||||
|
"""كشف التهديدات بناءً على الأنماط"""
|
||||||
|
threat = THREAT_PATTERNS.get(threat_type)
|
||||||
|
if not threat or 'patterns' not in threat:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# البحث في الحقول المناسبة
|
||||||
|
search_fields = ['path', 'message', 'user_agent', 'referer']
|
||||||
|
for field in search_fields:
|
||||||
|
if field in log_entry:
|
||||||
|
for pattern in threat['patterns']:
|
||||||
|
if re.search(pattern, str(log_entry[field]), re.IGNORECASE):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def analyze_log_entry(self, entry: Dict):
|
||||||
|
"""تحليل سجل واحد للكشف عن التهديدات"""
|
||||||
|
if not entry:
|
||||||
|
return
|
||||||
|
|
||||||
|
ip = entry.get('ip', 'unknown')
|
||||||
|
|
||||||
|
# تحديث معلومات IP
|
||||||
|
self.suspicious_ips[ip]['count'] += 1
|
||||||
|
if not self.suspicious_ips[ip]['first_seen']:
|
||||||
|
self.suspicious_ips[ip]['first_seen'] = entry.get('timestamp')
|
||||||
|
self.suspicious_ips[ip]['last_seen'] = entry.get('timestamp')
|
||||||
|
|
||||||
|
# كشف SQL Injection
|
||||||
|
if self.detect_pattern_threat(entry, 'sql_injection'):
|
||||||
|
self.add_alert('sql_injection', entry)
|
||||||
|
|
||||||
|
# كشف XSS
|
||||||
|
if self.detect_pattern_threat(entry, 'xss_attempt'):
|
||||||
|
self.add_alert('xss_attempt', entry)
|
||||||
|
|
||||||
|
# كشف Path Traversal
|
||||||
|
if self.detect_pattern_threat(entry, 'path_traversal'):
|
||||||
|
self.add_alert('path_traversal', entry)
|
||||||
|
|
||||||
|
# كشف User-Agent مشبوه
|
||||||
|
if self.detect_pattern_threat(entry, 'suspicious_user_agent'):
|
||||||
|
self.add_alert('suspicious_user_agent', entry)
|
||||||
|
|
||||||
|
# كشف محاولات تسجيل دخول فاشلة
|
||||||
|
if entry.get('event') == 'failed_login':
|
||||||
|
self.suspicious_ips[ip]['threats'].append('failed_login')
|
||||||
|
if len([t for t in self.suspicious_ips[ip]['threats'] if t == 'failed_login']) >= 5:
|
||||||
|
self.add_alert('brute_force', entry)
|
||||||
|
|
||||||
|
# كشف أكواد HTTP مشبوهة
|
||||||
|
status = entry.get('status')
|
||||||
|
if status:
|
||||||
|
if status == 401 or status == 403:
|
||||||
|
self.suspicious_ips[ip]['threats'].append('auth_failure')
|
||||||
|
elif status >= 500:
|
||||||
|
self.suspicious_ips[ip]['threats'].append('server_error')
|
||||||
|
|
||||||
|
def add_alert(self, threat_type: str, entry: Dict):
|
||||||
|
"""إضافة تنبيه جديد"""
|
||||||
|
threat_info = THREAT_PATTERNS.get(threat_type, {})
|
||||||
|
alert = {
|
||||||
|
'id': hashlib.md5(f"{threat_type}{entry.get('ip')}{datetime.now()}".encode()).hexdigest()[:8],
|
||||||
|
'timestamp': datetime.now().isoformat(),
|
||||||
|
'threat_type': threat_type,
|
||||||
|
'description': threat_info.get('description', threat_type),
|
||||||
|
'severity': threat_info.get('severity', 'medium'),
|
||||||
|
'source_ip': entry.get('ip', 'unknown'),
|
||||||
|
'details': entry,
|
||||||
|
'status': 'new'
|
||||||
|
}
|
||||||
|
self.alerts.append(alert)
|
||||||
|
self.stats['threats_detected'] += 1
|
||||||
|
|
||||||
|
def analyze_file(self, source_name: str, filepath: str):
|
||||||
|
"""تحليل ملف سجلات"""
|
||||||
|
if not os.path.exists(filepath):
|
||||||
|
print(f"⚠️ الملف غير موجود: {filepath}")
|
||||||
|
return
|
||||||
|
|
||||||
|
parser = {
|
||||||
|
'nginx': self.parse_nginx_log,
|
||||||
|
'auth': self.parse_auth_log,
|
||||||
|
'app': self.parse_app_log
|
||||||
|
}.get(source_name)
|
||||||
|
|
||||||
|
if not parser:
|
||||||
|
print(f"⚠️ لا يوجد محلل لـ: {source_name}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"📂 تحليل {source_name}: {filepath}")
|
||||||
|
|
||||||
|
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
|
||||||
|
for line in f:
|
||||||
|
self.stats['total_lines'] += 1
|
||||||
|
entry = parser(line.strip())
|
||||||
|
if entry:
|
||||||
|
self.analyze_log_entry(entry)
|
||||||
|
|
||||||
|
self.stats['sources_analyzed'] += 1
|
||||||
|
|
||||||
|
def analyze_all(self):
|
||||||
|
"""تحليل جميع المصادر"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("🔍 بدء تحليل السجلات - SIEM مبسط")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
for source_name, filepath in self.sources.items():
|
||||||
|
self.analyze_file(source_name, filepath)
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("📊 نتائج التحليل")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
def get_suspicious_ips(self, min_threats: int = 3) -> List[Dict]:
|
||||||
|
"""الحصول على قائمة IPs المشبوهة"""
|
||||||
|
suspicious = []
|
||||||
|
for ip, data in self.suspicious_ips.items():
|
||||||
|
threat_count = len(data['threats'])
|
||||||
|
if threat_count >= min_threats:
|
||||||
|
suspicious.append({
|
||||||
|
'ip': ip,
|
||||||
|
'request_count': data['count'],
|
||||||
|
'threat_count': threat_count,
|
||||||
|
'threats': list(set(data['threats'])),
|
||||||
|
'first_seen': data['first_seen'],
|
||||||
|
'last_seen': data['last_seen']
|
||||||
|
})
|
||||||
|
return sorted(suspicious, key=lambda x: x['threat_count'], reverse=True)
|
||||||
|
|
||||||
|
def get_alerts_by_severity(self) -> Dict[str, List]:
|
||||||
|
"""تجميع التنبيهات حسب الخطورة"""
|
||||||
|
by_severity = defaultdict(list)
|
||||||
|
for alert in self.alerts:
|
||||||
|
by_severity[alert['severity']].append(alert)
|
||||||
|
return dict(by_severity)
|
||||||
|
|
||||||
|
def generate_report(self) -> Dict:
|
||||||
|
"""إنشاء تقرير شامل"""
|
||||||
|
return {
|
||||||
|
'generated_at': datetime.now().isoformat(),
|
||||||
|
'statistics': self.stats,
|
||||||
|
'alerts': self.alerts,
|
||||||
|
'alerts_by_severity': self.get_alerts_by_severity(),
|
||||||
|
'suspicious_ips': self.get_suspicious_ips(),
|
||||||
|
'summary': {
|
||||||
|
'total_alerts': len(self.alerts),
|
||||||
|
'critical': len([a for a in self.alerts if a['severity'] == 'critical']),
|
||||||
|
'high': len([a for a in self.alerts if a['severity'] == 'high']),
|
||||||
|
'medium': len([a for a in self.alerts if a['severity'] == 'medium']),
|
||||||
|
'suspicious_ips_count': len(self.get_suspicious_ips())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def print_summary(self):
|
||||||
|
"""طباعة ملخص النتائج"""
|
||||||
|
report = self.generate_report()
|
||||||
|
|
||||||
|
print(f"\n📈 الإحصائيات:")
|
||||||
|
print(f" - إجمالي الأسطر المحللة: {report['statistics']['total_lines']}")
|
||||||
|
print(f" - المصادر المحللة: {report['statistics']['sources_analyzed']}")
|
||||||
|
print(f" - التهديدات المكتشفة: {report['statistics']['threats_detected']}")
|
||||||
|
|
||||||
|
print(f"\n🚨 التنبيهات حسب الخطورة:")
|
||||||
|
print(f" - حرجة (Critical): {report['summary']['critical']}")
|
||||||
|
print(f" - عالية (High): {report['summary']['high']}")
|
||||||
|
print(f" - متوسطة (Medium): {report['summary']['medium']}")
|
||||||
|
|
||||||
|
print(f"\n🔴 عناوين IP المشبوهة ({report['summary']['suspicious_ips_count']}):")
|
||||||
|
for ip_data in report['suspicious_ips'][:10]:
|
||||||
|
print(f" - {ip_data['ip']}: {ip_data['threat_count']} تهديدات, {ip_data['request_count']} طلبات")
|
||||||
|
|
||||||
|
if self.alerts:
|
||||||
|
print(f"\n⚠️ آخر 5 تنبيهات:")
|
||||||
|
for alert in self.alerts[-5:]:
|
||||||
|
print(f" [{alert['severity'].upper()}] {alert['description']} من {alert['source_ip']}")
|
||||||
|
|
||||||
|
def export_json(self, filepath: str):
|
||||||
|
"""تصدير التقرير كـ JSON"""
|
||||||
|
report = self.generate_report()
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(report, f, ensure_ascii=False, indent=2)
|
||||||
|
print(f"\n💾 تم حفظ التقرير: {filepath}")
|
||||||
|
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# إنشاء ملفات سجلات تجريبية
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
def create_sample_logs():
|
||||||
|
"""إنشاء ملفات سجلات تجريبية للاختبار"""
|
||||||
|
os.makedirs('sample_logs', exist_ok=True)
|
||||||
|
|
||||||
|
# Nginx sample logs
|
||||||
|
nginx_logs = """192.168.1.100 - - [26/Jul/2026:14:05:01 +0000] "POST /api/login HTTP/1.1" 401 45 "-" "Mozilla/5.0"
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:05:02 +0000] "POST /api/login HTTP/1.1" 401 45 "-" "Mozilla/5.0"
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:05:03 +0000] "POST /api/login HTTP/1.1" 401 45 "-" "Mozilla/5.0"
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:05:04 +0000] "POST /api/login HTTP/1.1" 401 45 "-" "Mozilla/5.0"
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:05:05 +0000] "POST /api/login HTTP/1.1" 401 45 "-" "Mozilla/5.0"
|
||||||
|
192.168.1.100 - - [26/Jul/2026:14:05:06 +0000] "POST /api/login HTTP/1.1" 200 512 "-" "Mozilla/5.0"
|
||||||
|
10.0.0.50 - - [26/Jul/2026:14:10:01 +0000] "GET /api/users?id=1' OR '1'='1 HTTP/1.1" 400 120 "-" "sqlmap/1.5"
|
||||||
|
10.0.0.50 - - [26/Jul/2026:14:10:02 +0000] "GET /api/users?id=1 UNION SELECT * FROM users HTTP/1.1" 400 120 "-" "sqlmap/1.5"
|
||||||
|
172.16.0.25 - - [26/Jul/2026:14:15:01 +0000] "GET /page?q=<script>alert('xss')</script> HTTP/1.1" 400 80 "-" "Mozilla/5.0"
|
||||||
|
172.16.0.25 - - [26/Jul/2026:14:15:02 +0000] "GET /../../etc/passwd HTTP/1.1" 403 50 "-" "Mozilla/5.0"
|
||||||
|
8.8.8.8 - - [26/Jul/2026:14:20:01 +0000] "GET / HTTP/1.1" 200 1024 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
|
||||||
|
8.8.8.8 - - [26/Jul/2026:14:20:02 +0000] "GET /about HTTP/1.1" 200 2048 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Auth sample logs
|
||||||
|
auth_logs = """Jul 26 14:00:01 server sshd[1234]: Failed password for invalid user admin from 192.168.1.200 port 22 ssh2
|
||||||
|
Jul 26 14:00:02 server sshd[1234]: Failed password for invalid user admin from 192.168.1.200 port 22 ssh2
|
||||||
|
Jul 26 14:00:03 server sshd[1234]: Failed password for invalid user root from 192.168.1.200 port 22 ssh2
|
||||||
|
Jul 26 14:00:04 server sshd[1234]: Failed password for invalid user test from 192.168.1.200 port 22 ssh2
|
||||||
|
Jul 26 14:00:05 server sshd[1234]: Failed password for invalid user user from 192.168.1.200 port 22 ssh2
|
||||||
|
Jul 26 14:05:01 server sshd[1235]: Accepted password for developer from 10.0.0.10 port 22 ssh2
|
||||||
|
"""
|
||||||
|
|
||||||
|
# App sample logs
|
||||||
|
app_logs = """[2026-07-26 14:00:01] [ERROR] [192.168.1.100] Login failed for user: admin
|
||||||
|
[2026-07-26 14:00:02] [ERROR] [192.168.1.100] Login failed for user: admin
|
||||||
|
[2026-07-26 14:00:03] [WARN] [10.0.0.50] Suspicious query detected: SELECT * FROM users
|
||||||
|
[2026-07-26 14:00:04] [INFO] [8.8.8.8] User logged in successfully
|
||||||
|
[2026-07-26 14:00:05] [ERROR] [172.16.0.25] Invalid input: <script>alert(1)</script>
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open('sample_logs/nginx_access.log', 'w') as f:
|
||||||
|
f.write(nginx_logs)
|
||||||
|
|
||||||
|
with open('sample_logs/auth.log', 'w') as f:
|
||||||
|
f.write(auth_logs)
|
||||||
|
|
||||||
|
with open('sample_logs/app.log', 'w') as f:
|
||||||
|
f.write(app_logs)
|
||||||
|
|
||||||
|
print("✅ تم إنشاء ملفات السجلات التجريبية في sample_logs/")
|
||||||
|
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# التشغيل الرئيسي
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# إنشاء ملفات تجريبية إذا لم تكن موجودة
|
||||||
|
if not os.path.exists('sample_logs'):
|
||||||
|
create_sample_logs()
|
||||||
|
|
||||||
|
# تحليل السجلات
|
||||||
|
analyzer = LogAnalyzer(use_sample=True)
|
||||||
|
analyzer.analyze_all()
|
||||||
|
analyzer.print_summary()
|
||||||
|
|
||||||
|
# تصدير التقرير
|
||||||
|
analyzer.export_json('siem_report.json')
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✅ اكتمل التحليل - راجع siem_report.json للتفاصيل")
|
||||||
|
print("=" * 60)
|
||||||
@@ -0,0 +1,357 @@
|
|||||||
|
# استراتيجية النسخ الاحتياطي والاستعادة - Ghaymah Backup & Recovery
|
||||||
|
## مع RPO/RTO وقاعدة 3-2-1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. فهم RPO و RTO
|
||||||
|
|
||||||
|
### تعريفات أساسية
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ │
|
||||||
|
│ آخر نسخة الحادثة استعادة الخدمة │
|
||||||
|
│ احتياطية ↓ ↓ │
|
||||||
|
│ ↓ ↓ ↓ │
|
||||||
|
│ ─────●───────────────●────────────────────●─────────────→ الوقت │
|
||||||
|
│ │ │ │ │
|
||||||
|
│ │←──── RPO ────→│←────── RTO ───────→│ │
|
||||||
|
│ │ │ │ │
|
||||||
|
│ البيانات التي وقت وقت العودة │
|
||||||
|
│ قد تُفقد الحادثة للعمل │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
| المصطلح | التعريف | مثال |
|
||||||
|
|---------|---------|------|
|
||||||
|
| **RPO** (Recovery Point Objective) | أقصى كمية بيانات يمكن خسارتها | RPO = 1 ساعة → نسخ احتياطي كل ساعة |
|
||||||
|
| **RTO** (Recovery Time Objective) | أقصى وقت للعودة للعمل | RTO = 4 ساعات → يجب استعادة الخدمة خلال 4 ساعات |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. قاعدة 3-2-1 للنسخ الاحتياطي
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ قاعدة 3-2-1 │
|
||||||
|
├─────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ 3️⃣ ثلاث نسخ من البيانات │
|
||||||
|
│ ├── النسخة الأصلية (Production) │
|
||||||
|
│ ├── النسخة الاحتياطية الأولى (Local Backup) │
|
||||||
|
│ └── النسخة الاحتياطية الثانية (Remote Backup) │
|
||||||
|
│ │
|
||||||
|
│ 2️⃣ نوعان مختلفان من وسائط التخزين │
|
||||||
|
│ ├── Block Storage (SSD) │
|
||||||
|
│ └── Object Storage (S3-compatible) │
|
||||||
|
│ │
|
||||||
|
│ 1️⃣ نسخة واحدة على الأقل خارج الموقع (Offsite) │
|
||||||
|
│ └── منطقة جغرافية مختلفة أو مزود سحابي آخر │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. تطبيق الاستراتيجية على غيمة
|
||||||
|
|
||||||
|
### البنية المقترحة
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ غيمة Cloud │
|
||||||
|
├─────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ │
|
||||||
|
│ │ Production │ ← النسخة الأصلية (1) │
|
||||||
|
│ │ Block Storage │ │
|
||||||
|
│ │ (me-riyadh-1) │ │
|
||||||
|
│ └────────┬────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ │ نسخ كل ساعة │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌─────────────────┐ │
|
||||||
|
│ │ Local Backup │ ← النسخة الاحتياطية (2) - وسيط مختلف │
|
||||||
|
│ │ Object Storage │ │
|
||||||
|
│ │ (me-riyadh-1) │ │
|
||||||
|
│ └────────┬────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ │ نسخ يومي │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌─────────────────┐ │
|
||||||
|
│ │ Offsite Backup │ ← النسخة الخارجية (3) - موقع مختلف │
|
||||||
|
│ │ Object Storage │ │
|
||||||
|
│ │ (me-jeddah-1) │ │
|
||||||
|
│ └─────────────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### تكوين النسخ الاحتياطي
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# backup-config.yaml
|
||||||
|
backup_strategy:
|
||||||
|
name: "3-2-1 Backup Strategy"
|
||||||
|
|
||||||
|
# النسخة الأصلية
|
||||||
|
production:
|
||||||
|
type: block-storage
|
||||||
|
location: me-riyadh-1
|
||||||
|
volume: prod-data
|
||||||
|
|
||||||
|
# النسخة الاحتياطية المحلية
|
||||||
|
local_backup:
|
||||||
|
type: object-storage
|
||||||
|
location: me-riyadh-1
|
||||||
|
bucket: backups-local
|
||||||
|
schedule:
|
||||||
|
frequency: hourly
|
||||||
|
retention: 72 # 72 ساعة = 3 أيام
|
||||||
|
encryption: AES-256
|
||||||
|
|
||||||
|
# النسخة الخارجية
|
||||||
|
offsite_backup:
|
||||||
|
type: object-storage
|
||||||
|
location: me-jeddah-1 # منطقة مختلفة
|
||||||
|
bucket: backups-offsite
|
||||||
|
schedule:
|
||||||
|
frequency: daily
|
||||||
|
time: "02:00"
|
||||||
|
retention: 30 # 30 يوم
|
||||||
|
encryption: AES-256
|
||||||
|
|
||||||
|
# أهداف الاستعادة
|
||||||
|
objectives:
|
||||||
|
rpo: 1h # أقصى خسارة = ساعة واحدة
|
||||||
|
rto: 4h # أقصى وقت استعادة = 4 ساعات
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. تنفيذ النسخ الاحتياطي على غيمة
|
||||||
|
|
||||||
|
### أ. إنشاء Buckets للنسخ الاحتياطي
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# إنشاء bucket محلي
|
||||||
|
ghaymah storage bucket create backups-local \
|
||||||
|
--region me-riyadh-1 \
|
||||||
|
--encryption AES-256 \
|
||||||
|
--versioning enabled
|
||||||
|
|
||||||
|
# إنشاء bucket خارجي
|
||||||
|
ghaymah storage bucket create backups-offsite \
|
||||||
|
--region me-jeddah-1 \
|
||||||
|
--encryption AES-256 \
|
||||||
|
--versioning enabled
|
||||||
|
```
|
||||||
|
|
||||||
|
### ب. إعداد جدول النسخ الاحتياطي
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# نسخ احتياطي كل ساعة (محلي)
|
||||||
|
ghaymah backup schedule create \
|
||||||
|
--name hourly-local \
|
||||||
|
--source prod-data \
|
||||||
|
--destination backups-local \
|
||||||
|
--frequency hourly \
|
||||||
|
--retention 72h
|
||||||
|
|
||||||
|
# نسخ احتياطي يومي (خارجي)
|
||||||
|
ghaymah backup schedule create \
|
||||||
|
--name daily-offsite \
|
||||||
|
--source prod-data \
|
||||||
|
--destination backups-offsite \
|
||||||
|
--frequency daily \
|
||||||
|
--time "02:00" \
|
||||||
|
--retention 30d
|
||||||
|
```
|
||||||
|
|
||||||
|
### ج. سكربت النسخ الاحتياطي
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# backup-script.sh - سكربت النسخ الاحتياطي التلقائي
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||||
|
SOURCE_VOLUME="prod-data"
|
||||||
|
LOCAL_BUCKET="backups-local"
|
||||||
|
OFFSITE_BUCKET="backups-offsite"
|
||||||
|
|
||||||
|
echo "[$TIMESTAMP] بدء النسخ الاحتياطي..."
|
||||||
|
|
||||||
|
# 1. إنشاء snapshot من Block Storage
|
||||||
|
echo "إنشاء snapshot..."
|
||||||
|
SNAPSHOT_ID=$(ghaymah storage snapshot create \
|
||||||
|
--volume $SOURCE_VOLUME \
|
||||||
|
--name "backup-$TIMESTAMP" \
|
||||||
|
--output json | jq -r '.id')
|
||||||
|
|
||||||
|
echo "تم إنشاء snapshot: $SNAPSHOT_ID"
|
||||||
|
|
||||||
|
# 2. نسخ إلى Object Storage المحلي
|
||||||
|
echo "نسخ إلى التخزين المحلي..."
|
||||||
|
ghaymah storage copy \
|
||||||
|
--source "snapshot:$SNAPSHOT_ID" \
|
||||||
|
--destination "s3://$LOCAL_BUCKET/backup-$TIMESTAMP.tar.gz" \
|
||||||
|
--compress \
|
||||||
|
--encrypt
|
||||||
|
|
||||||
|
# 3. نسخ إلى Object Storage الخارجي (يومياً فقط)
|
||||||
|
HOUR=$(date +%H)
|
||||||
|
if [ "$HOUR" == "02" ]; then
|
||||||
|
echo "نسخ إلى التخزين الخارجي..."
|
||||||
|
ghaymah storage copy \
|
||||||
|
--source "s3://$LOCAL_BUCKET/backup-$TIMESTAMP.tar.gz" \
|
||||||
|
--destination "s3://$OFFSITE_BUCKET/backup-$TIMESTAMP.tar.gz"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. تنظيف النسخ القديمة
|
||||||
|
echo "تنظيف النسخ القديمة..."
|
||||||
|
ghaymah backup cleanup \
|
||||||
|
--bucket $LOCAL_BUCKET \
|
||||||
|
--older-than 72h
|
||||||
|
|
||||||
|
ghaymah backup cleanup \
|
||||||
|
--bucket $OFFSITE_BUCKET \
|
||||||
|
--older-than 30d
|
||||||
|
|
||||||
|
# 5. التحقق من النسخة
|
||||||
|
echo "التحقق من سلامة النسخة..."
|
||||||
|
ghaymah backup verify \
|
||||||
|
--backup "s3://$LOCAL_BUCKET/backup-$TIMESTAMP.tar.gz"
|
||||||
|
|
||||||
|
echo "[$TIMESTAMP] اكتمل النسخ الاحتياطي بنجاح ✓"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. إجراءات الاستعادة
|
||||||
|
|
||||||
|
### سيناريو: استعادة بعد Ransomware
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# restore-script.sh - سكربت الاستعادة
|
||||||
|
|
||||||
|
echo "🔄 بدء عملية الاستعادة..."
|
||||||
|
|
||||||
|
# 1. تحديد آخر نسخة سليمة
|
||||||
|
echo "البحث عن آخر نسخة سليمة..."
|
||||||
|
LATEST_BACKUP=$(ghaymah backup list \
|
||||||
|
--bucket backups-local \
|
||||||
|
--status verified \
|
||||||
|
--limit 1 \
|
||||||
|
--output json | jq -r '.[0].name')
|
||||||
|
|
||||||
|
echo "آخر نسخة سليمة: $LATEST_BACKUP"
|
||||||
|
|
||||||
|
# 2. إنشاء volume جديد للاستعادة
|
||||||
|
echo "إنشاء volume جديد..."
|
||||||
|
ghaymah storage volume create \
|
||||||
|
--name restored-data \
|
||||||
|
--size 100GB \
|
||||||
|
--type ssd
|
||||||
|
|
||||||
|
# 3. استعادة البيانات
|
||||||
|
echo "استعادة البيانات..."
|
||||||
|
ghaymah backup restore \
|
||||||
|
--source "s3://backups-local/$LATEST_BACKUP" \
|
||||||
|
--destination restored-data \
|
||||||
|
--verify
|
||||||
|
|
||||||
|
# 4. التحقق من البيانات
|
||||||
|
echo "التحقق من البيانات المستعادة..."
|
||||||
|
ghaymah storage verify --volume restored-data
|
||||||
|
|
||||||
|
# 5. تبديل الـ volumes
|
||||||
|
echo "تبديل إلى البيانات المستعادة..."
|
||||||
|
ghaymah storage swap \
|
||||||
|
--old prod-data \
|
||||||
|
--new restored-data
|
||||||
|
|
||||||
|
echo "✅ اكتملت الاستعادة بنجاح!"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. جدول RPO/RTO حسب نوع البيانات
|
||||||
|
|
||||||
|
| نوع البيانات | RPO | RTO | تكرار النسخ | الاحتفاظ |
|
||||||
|
|--------------|-----|-----|-------------|----------|
|
||||||
|
| **قواعد البيانات** | 15 دقيقة | 1 ساعة | كل 15 دقيقة | 7 أيام |
|
||||||
|
| **ملفات التطبيق** | 1 ساعة | 2 ساعة | كل ساعة | 30 يوم |
|
||||||
|
| **سجلات النظام** | 4 ساعات | 8 ساعات | كل 4 ساعات | 90 يوم |
|
||||||
|
| **الأرشيف** | 24 ساعة | 24 ساعة | يومي | سنة |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. اختبار الاستعادة الدوري
|
||||||
|
|
||||||
|
### جدول الاختبار
|
||||||
|
|
||||||
|
| الاختبار | التكرار | المسؤول |
|
||||||
|
|----------|---------|---------|
|
||||||
|
| استعادة ملف واحد | أسبوعي | DevOps |
|
||||||
|
| استعادة قاعدة بيانات | شهري | DBA |
|
||||||
|
| استعادة كاملة (DR) | ربع سنوي | فريق الأمن |
|
||||||
|
|
||||||
|
### سكربت اختبار الاستعادة
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# test-restore.sh - اختبار الاستعادة
|
||||||
|
|
||||||
|
echo "🧪 بدء اختبار الاستعادة..."
|
||||||
|
|
||||||
|
# إنشاء بيئة اختبار
|
||||||
|
ghaymah project create restore-test --temporary
|
||||||
|
|
||||||
|
# استعادة من آخر نسخة
|
||||||
|
ghaymah backup restore \
|
||||||
|
--source backups-local/latest \
|
||||||
|
--destination restore-test \
|
||||||
|
--verify
|
||||||
|
|
||||||
|
# اختبار البيانات
|
||||||
|
ghaymah test run \
|
||||||
|
--project restore-test \
|
||||||
|
--suite data-integrity
|
||||||
|
|
||||||
|
# تنظيف
|
||||||
|
ghaymah project delete restore-test --force
|
||||||
|
|
||||||
|
echo "✅ اختبار الاستعادة ناجح!"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. ملخص الاستراتيجية
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ ملخص استراتيجية 3-2-1 │
|
||||||
|
├─────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ 📦 3 نسخ: │
|
||||||
|
│ • Production (Block Storage - Riyadh) │
|
||||||
|
│ • Local Backup (Object Storage - Riyadh) │
|
||||||
|
│ • Offsite Backup (Object Storage - Jeddah) │
|
||||||
|
│ │
|
||||||
|
│ 💾 2 وسيط: │
|
||||||
|
│ • Block Storage (SSD) │
|
||||||
|
│ • Object Storage (S3) │
|
||||||
|
│ │
|
||||||
|
│ 🌍 1 خارج الموقع: │
|
||||||
|
│ • منطقة جدة (me-jeddah-1) │
|
||||||
|
│ │
|
||||||
|
│ ⏱️ الأهداف: │
|
||||||
|
│ • RPO: 1 ساعة (أقصى خسارة بيانات) │
|
||||||
|
│ • RTO: 4 ساعات (أقصى وقت توقف) │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
# خطة طوارئ لحادثة Ransomware
|
||||||
|
## السيناريو: جميع ملفات Block Storage على غيمة تم تشفيرها برسالة فدية
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⏱️ أول 60 دقيقة - خطة الاستجابة الطارئة
|
||||||
|
|
||||||
|
### الدقائق 0-5: الاكتشاف والتأكيد
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 🚨 تأكيد الحادثة │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ □ التحقق من رسالة الفدية │
|
||||||
|
│ □ تحديد نطاق التشفير (أي volumes متأثرة؟) │
|
||||||
|
│ □ توثيق الوقت الدقيق للاكتشاف │
|
||||||
|
│ □ أخذ screenshots للأدلة │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**الإجراءات:**
|
||||||
|
1. **لا تدفع الفدية** - لا ضمان لاسترجاع البيانات
|
||||||
|
2. **لا تحذف رسالة الفدية** - قد تحتوي على معلومات مفيدة
|
||||||
|
3. **وثّق كل شيء** - screenshots، أوقات، ملاحظات
|
||||||
|
|
||||||
|
### الدقائق 5-15: العزل الفوري
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. فصل الأنظمة المتأثرة عن الشبكة
|
||||||
|
# من لوحة تحكم غيمة:
|
||||||
|
ghaymah network isolate --project affected-project
|
||||||
|
|
||||||
|
# 2. إيقاف جميع الحاويات المتأثرة
|
||||||
|
ghaymah containers stop --all --project affected-project
|
||||||
|
|
||||||
|
# 3. منع الوصول الخارجي
|
||||||
|
ghaymah firewall deny --all-inbound --project affected-project
|
||||||
|
```
|
||||||
|
|
||||||
|
**قائمة العزل:**
|
||||||
|
- [ ] فصل Block Storage المتأثر
|
||||||
|
- [ ] إيقاف التطبيقات المتصلة
|
||||||
|
- [ ] حظر جميع الاتصالات الواردة
|
||||||
|
- [ ] تعطيل حسابات المستخدمين المشبوهة
|
||||||
|
- [ ] فصل أي أنظمة متصلة بنفس الشبكة
|
||||||
|
|
||||||
|
### الدقائق 15-30: تقييم الضرر
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 📊 تقييم النطاق │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ الأسئلة المطلوب الإجابة عليها: │
|
||||||
|
│ │
|
||||||
|
│ 1. ما هي الـ Volumes المتأثرة؟ │
|
||||||
|
│ □ Block Storage الرئيسي │
|
||||||
|
│ □ قواعد البيانات │
|
||||||
|
│ □ النسخ الاحتياطية │
|
||||||
|
│ │
|
||||||
|
│ 2. هل النسخ الاحتياطية سليمة؟ │
|
||||||
|
│ □ فحص آخر نسخة احتياطية │
|
||||||
|
│ □ التحقق من عدم تشفيرها │
|
||||||
|
│ │
|
||||||
|
│ 3. كيف دخل المهاجم؟ │
|
||||||
|
│ □ مراجعة سجلات الدخول │
|
||||||
|
│ □ فحص الثغرات المحتملة │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**أوامر الفحص:**
|
||||||
|
```bash
|
||||||
|
# فحص حالة الـ Volumes
|
||||||
|
ghaymah storage list --status
|
||||||
|
|
||||||
|
# فحص النسخ الاحتياطية
|
||||||
|
ghaymah backup list --project affected-project
|
||||||
|
|
||||||
|
# مراجعة سجلات الدخول
|
||||||
|
ghaymah logs auth --since "24h" --project affected-project
|
||||||
|
```
|
||||||
|
|
||||||
|
### الدقائق 30-45: التواصل والإبلاغ
|
||||||
|
|
||||||
|
**جهات الاتصال الفورية:**
|
||||||
|
|
||||||
|
| الجهة | الإجراء | الأولوية |
|
||||||
|
|-------|---------|----------|
|
||||||
|
| فريق الأمن الداخلي | إبلاغ فوري | 🔴 حرج |
|
||||||
|
| دعم غيمة | فتح تذكرة طوارئ | 🔴 حرج |
|
||||||
|
| الإدارة العليا | إبلاغ مختصر | 🟡 عالي |
|
||||||
|
| الفريق القانوني | استشارة | 🟡 عالي |
|
||||||
|
| الجهات الرقابية | إبلاغ (إذا مطلوب قانونياً) | 🟡 عالي |
|
||||||
|
|
||||||
|
**نموذج الإبلاغ:**
|
||||||
|
```
|
||||||
|
الموضوع: [طوارئ] حادثة Ransomware - [اسم المشروع]
|
||||||
|
|
||||||
|
الوقت: [التاريخ والوقت]
|
||||||
|
النطاق: [الأنظمة المتأثرة]
|
||||||
|
الحالة: [قيد الاحتواء]
|
||||||
|
|
||||||
|
الإجراءات المتخذة:
|
||||||
|
1. عزل الأنظمة المتأثرة
|
||||||
|
2. إيقاف الخدمات
|
||||||
|
3. بدء التحقيق
|
||||||
|
|
||||||
|
الخطوات التالية:
|
||||||
|
1. تقييم النسخ الاحتياطية
|
||||||
|
2. تحديد نقطة الدخول
|
||||||
|
3. بدء الاستعادة
|
||||||
|
```
|
||||||
|
|
||||||
|
### الدقائق 45-60: بدء الاستعادة
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. التحقق من سلامة النسخ الاحتياطية
|
||||||
|
ghaymah backup verify --latest --project affected-project
|
||||||
|
|
||||||
|
# 2. إنشاء بيئة استعادة معزولة
|
||||||
|
ghaymah project create recovery-environment --isolated
|
||||||
|
|
||||||
|
# 3. استعادة من آخر نسخة سليمة
|
||||||
|
ghaymah backup restore \
|
||||||
|
--backup-id [BACKUP_ID] \
|
||||||
|
--to recovery-environment \
|
||||||
|
--verify
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 قائمة التحقق الشاملة (أول 60 دقيقة)
|
||||||
|
|
||||||
|
### المرحلة 1: الاكتشاف (0-5 دقائق)
|
||||||
|
- [ ] تأكيد أن الحادثة حقيقية وليست إنذار كاذب
|
||||||
|
- [ ] توثيق رسالة الفدية (screenshot)
|
||||||
|
- [ ] تسجيل الوقت الدقيق
|
||||||
|
- [ ] إبلاغ قائد الاستجابة للحوادث
|
||||||
|
|
||||||
|
### المرحلة 2: العزل (5-15 دقيقة)
|
||||||
|
- [ ] فصل الأنظمة المتأثرة عن الشبكة
|
||||||
|
- [ ] إيقاف جميع الحاويات والخدمات
|
||||||
|
- [ ] حظر الاتصالات الخارجية
|
||||||
|
- [ ] تعطيل الحسابات المشبوهة
|
||||||
|
- [ ] فصل VPN/API connections
|
||||||
|
|
||||||
|
### المرحلة 3: التقييم (15-30 دقيقة)
|
||||||
|
- [ ] تحديد جميع الـ Volumes المتأثرة
|
||||||
|
- [ ] فحص حالة النسخ الاحتياطية
|
||||||
|
- [ ] مراجعة سجلات الدخول
|
||||||
|
- [ ] تحديد نقطة الدخول المحتملة
|
||||||
|
- [ ] تقدير حجم البيانات المتأثرة
|
||||||
|
|
||||||
|
### المرحلة 4: التواصل (30-45 دقيقة)
|
||||||
|
- [ ] إبلاغ فريق الأمن
|
||||||
|
- [ ] فتح تذكرة طوارئ مع غيمة
|
||||||
|
- [ ] إبلاغ الإدارة
|
||||||
|
- [ ] استشارة الفريق القانوني
|
||||||
|
- [ ] تحضير بيان للعملاء (إذا لزم)
|
||||||
|
|
||||||
|
### المرحلة 5: الاستعادة (45-60 دقيقة)
|
||||||
|
- [ ] التحقق من سلامة النسخ الاحتياطية
|
||||||
|
- [ ] إنشاء بيئة استعادة معزولة
|
||||||
|
- [ ] بدء استعادة البيانات الحرجة
|
||||||
|
- [ ] اختبار البيانات المستعادة
|
||||||
|
- [ ] توثيق جميع الإجراءات
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ ما يجب تجنبه
|
||||||
|
|
||||||
|
| ❌ لا تفعل | ✅ افعل بدلاً |
|
||||||
|
|-----------|--------------|
|
||||||
|
| دفع الفدية | استخدم النسخ الاحتياطية |
|
||||||
|
| حذف الملفات المشفرة | احتفظ بها للتحليل |
|
||||||
|
| إعادة تشغيل الأنظمة | اعزلها أولاً |
|
||||||
|
| تجاهل الحادثة | وثّق كل شيء |
|
||||||
|
| العمل بمفردك | أشرك الفريق |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 أرقام الطوارئ
|
||||||
|
|
||||||
|
```
|
||||||
|
دعم غيمة (طوارئ): support@ghaymah.systems
|
||||||
|
فريق الأمن الداخلي: [رقم الهاتف]
|
||||||
|
قائد الاستجابة للحوادث: [رقم الهاتف]
|
||||||
|
```
|
||||||
@@ -0,0 +1,558 @@
|
|||||||
|
# خطة وقاية شاملة لمنع تكرار هجوم Ransomware
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. نظرة عامة
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ طبقات الحماية من Ransomware │
|
||||||
|
├─────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ طبقة 1: الوقاية │ │
|
||||||
|
│ │ (منع الدخول - Access Prevention) │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────────┘ │
|
||||||
|
│ ↓ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ طبقة 2: الكشف │ │
|
||||||
|
│ │ (اكتشاف مبكر - Early Detection) │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────────┘ │
|
||||||
|
│ ↓ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ طبقة 3: الاحتواء │ │
|
||||||
|
│ │ (تقليل الضرر - Damage Limitation) │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────────┘ │
|
||||||
|
│ ↓ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ طبقة 4: الاستعادة │ │
|
||||||
|
│ │ (العودة للعمل - Recovery) │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. طبقة الوقاية (Prevention)
|
||||||
|
|
||||||
|
### أ. إدارة الهوية والوصول (IAM)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# سياسة IAM صارمة
|
||||||
|
iam_policy:
|
||||||
|
# مبدأ أقل صلاحية
|
||||||
|
principle: least_privilege
|
||||||
|
|
||||||
|
# المصادقة متعددة العوامل
|
||||||
|
mfa:
|
||||||
|
required: true
|
||||||
|
methods:
|
||||||
|
- authenticator_app
|
||||||
|
- hardware_key
|
||||||
|
enforce_for:
|
||||||
|
- all_admin_accounts
|
||||||
|
- api_access
|
||||||
|
- ssh_access
|
||||||
|
|
||||||
|
# سياسة كلمات المرور
|
||||||
|
password_policy:
|
||||||
|
min_length: 14
|
||||||
|
require_uppercase: true
|
||||||
|
require_lowercase: true
|
||||||
|
require_numbers: true
|
||||||
|
require_symbols: true
|
||||||
|
max_age_days: 90
|
||||||
|
prevent_reuse: 12
|
||||||
|
|
||||||
|
# مراجعة الصلاحيات
|
||||||
|
access_review:
|
||||||
|
frequency: monthly
|
||||||
|
auto_revoke_inactive: 30d
|
||||||
|
```
|
||||||
|
|
||||||
|
**التنفيذ على غيمة:**
|
||||||
|
```bash
|
||||||
|
# تفعيل MFA لجميع المستخدمين
|
||||||
|
ghaymah iam policy update \
|
||||||
|
--require-mfa true \
|
||||||
|
--apply-to all-users
|
||||||
|
|
||||||
|
# إنشاء أدوار محددة
|
||||||
|
ghaymah iam role create \
|
||||||
|
--name developer \
|
||||||
|
--permissions "read:code,write:code,read:logs" \
|
||||||
|
--deny "admin:*,delete:*"
|
||||||
|
|
||||||
|
ghaymah iam role create \
|
||||||
|
--name operator \
|
||||||
|
--permissions "read:*,restart:services" \
|
||||||
|
--deny "delete:*,modify:iam"
|
||||||
|
```
|
||||||
|
|
||||||
|
### ب. أمان الشبكة
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Network Security Configuration
|
||||||
|
network_security:
|
||||||
|
# جدار الحماية
|
||||||
|
firewall:
|
||||||
|
default_policy: deny
|
||||||
|
allowed_inbound:
|
||||||
|
- port: 443
|
||||||
|
source: "0.0.0.0/0"
|
||||||
|
protocol: tcp
|
||||||
|
- port: 22
|
||||||
|
source: "10.0.0.0/8" # VPN فقط
|
||||||
|
protocol: tcp
|
||||||
|
|
||||||
|
# تقسيم الشبكة
|
||||||
|
segmentation:
|
||||||
|
- name: production
|
||||||
|
cidr: "10.1.0.0/16"
|
||||||
|
access: restricted
|
||||||
|
- name: backup
|
||||||
|
cidr: "10.2.0.0/16"
|
||||||
|
access: isolated # معزولة تماماً
|
||||||
|
- name: management
|
||||||
|
cidr: "10.3.0.0/16"
|
||||||
|
access: admin_only
|
||||||
|
|
||||||
|
# VPN إجباري للإدارة
|
||||||
|
vpn:
|
||||||
|
required_for: admin_access
|
||||||
|
type: wireguard
|
||||||
|
mfa: required
|
||||||
|
```
|
||||||
|
|
||||||
|
**Network Policies:**
|
||||||
|
```yaml
|
||||||
|
# kubernetes network policy
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: isolate-backup-storage
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: backup-storage
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
|
- Egress
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
role: backup-agent
|
||||||
|
ports:
|
||||||
|
- port: 443
|
||||||
|
egress: [] # لا اتصال خارجي
|
||||||
|
```
|
||||||
|
|
||||||
|
### ج. أمان النقاط الطرفية (Endpoint Security)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
endpoint_security:
|
||||||
|
# مكافح الفيروسات
|
||||||
|
antivirus:
|
||||||
|
enabled: true
|
||||||
|
real_time_scan: true
|
||||||
|
scheduled_scan: daily
|
||||||
|
|
||||||
|
# كشف التهديدات
|
||||||
|
edr:
|
||||||
|
enabled: true
|
||||||
|
behavioral_analysis: true
|
||||||
|
ransomware_protection: true
|
||||||
|
|
||||||
|
# التحديثات التلقائية
|
||||||
|
patching:
|
||||||
|
auto_update: true
|
||||||
|
critical_patches: immediate
|
||||||
|
regular_patches: weekly
|
||||||
|
reboot_window: "02:00-04:00"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. طبقة الكشف (Detection)
|
||||||
|
|
||||||
|
### أ. نظام SIEM والمراقبة
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# تكوين المراقبة
|
||||||
|
monitoring:
|
||||||
|
# مصادر السجلات
|
||||||
|
log_sources:
|
||||||
|
- nginx_access
|
||||||
|
- nginx_error
|
||||||
|
- auth_logs
|
||||||
|
- app_logs
|
||||||
|
- system_logs
|
||||||
|
- audit_logs
|
||||||
|
|
||||||
|
# قواعد الكشف
|
||||||
|
detection_rules:
|
||||||
|
- name: mass_file_encryption
|
||||||
|
description: كشف تشفير ملفات جماعي
|
||||||
|
condition: |
|
||||||
|
file_operations.encrypt > 100
|
||||||
|
AND time_window < 5m
|
||||||
|
severity: critical
|
||||||
|
action: alert_and_isolate
|
||||||
|
|
||||||
|
- name: suspicious_process
|
||||||
|
description: عملية مشبوهة
|
||||||
|
condition: |
|
||||||
|
process.name IN ['vssadmin', 'wmic', 'bcdedit']
|
||||||
|
OR process.command CONTAINS 'shadow'
|
||||||
|
severity: high
|
||||||
|
action: alert
|
||||||
|
|
||||||
|
- name: unusual_network_activity
|
||||||
|
description: نشاط شبكة غير طبيعي
|
||||||
|
condition: |
|
||||||
|
outbound_connections > baseline * 3
|
||||||
|
OR connection_to_tor = true
|
||||||
|
severity: high
|
||||||
|
action: alert
|
||||||
|
```
|
||||||
|
|
||||||
|
### ب. تنبيهات Prometheus
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# prometheus-alerts.yaml
|
||||||
|
groups:
|
||||||
|
- name: ransomware_detection
|
||||||
|
rules:
|
||||||
|
- alert: MassFileModification
|
||||||
|
expr: |
|
||||||
|
rate(file_modifications_total[5m]) > 1000
|
||||||
|
for: 1m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
summary: "🚨 كشف تعديل ملفات جماعي"
|
||||||
|
description: "أكثر من 1000 ملف تم تعديله في 5 دقائق"
|
||||||
|
action: "عزل النظام فوراً"
|
||||||
|
|
||||||
|
- alert: SuspiciousFileExtension
|
||||||
|
expr: |
|
||||||
|
increase(files_with_extension{ext=~".*encrypted.*|.*locked.*|.*crypto.*"}[5m]) > 10
|
||||||
|
for: 0m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
summary: "🔒 كشف امتدادات ملفات مشبوهة"
|
||||||
|
description: "ملفات بامتدادات ransomware معروفة"
|
||||||
|
|
||||||
|
- alert: BackupDeletionAttempt
|
||||||
|
expr: |
|
||||||
|
backup_deletion_attempts > 0
|
||||||
|
for: 0m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
summary: "⚠️ محاولة حذف النسخ الاحتياطية"
|
||||||
|
description: "كشف محاولة حذف النسخ الاحتياطية"
|
||||||
|
```
|
||||||
|
|
||||||
|
### ج. File Integrity Monitoring (FIM)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# تكوين مراقبة سلامة الملفات
|
||||||
|
fim_config:
|
||||||
|
monitored_paths:
|
||||||
|
- path: /etc
|
||||||
|
recursive: true
|
||||||
|
alert_on: [create, modify, delete]
|
||||||
|
- path: /var/www
|
||||||
|
recursive: true
|
||||||
|
alert_on: [modify, delete]
|
||||||
|
- path: /home
|
||||||
|
recursive: true
|
||||||
|
alert_on: [mass_modify] # أكثر من 100 ملف
|
||||||
|
|
||||||
|
baseline:
|
||||||
|
update_frequency: daily
|
||||||
|
time: "03:00"
|
||||||
|
|
||||||
|
exclusions:
|
||||||
|
- "*.log"
|
||||||
|
- "*.tmp"
|
||||||
|
- "/var/cache/*"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. طبقة الاحتواء (Containment)
|
||||||
|
|
||||||
|
### أ. العزل التلقائي
|
||||||
|
|
||||||
|
```python
|
||||||
|
# auto_isolate.py - سكربت العزل التلقائي
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def isolate_system(reason: str):
|
||||||
|
"""عزل النظام تلقائياً عند كشف تهديد"""
|
||||||
|
|
||||||
|
timestamp = datetime.now().isoformat()
|
||||||
|
|
||||||
|
# 1. قطع الاتصال بالشبكة
|
||||||
|
subprocess.run([
|
||||||
|
"ghaymah", "network", "isolate",
|
||||||
|
"--project", "production",
|
||||||
|
"--reason", reason
|
||||||
|
])
|
||||||
|
|
||||||
|
# 2. إيقاف الخدمات غير الحرجة
|
||||||
|
subprocess.run([
|
||||||
|
"ghaymah", "services", "stop",
|
||||||
|
"--exclude", "backup,monitoring",
|
||||||
|
"--project", "production"
|
||||||
|
])
|
||||||
|
|
||||||
|
# 3. تفعيل وضع القراءة فقط للتخزين
|
||||||
|
subprocess.run([
|
||||||
|
"ghaymah", "storage", "readonly",
|
||||||
|
"--volume", "prod-data",
|
||||||
|
"--enable"
|
||||||
|
])
|
||||||
|
|
||||||
|
# 4. إرسال تنبيه
|
||||||
|
send_alert({
|
||||||
|
"type": "system_isolated",
|
||||||
|
"reason": reason,
|
||||||
|
"timestamp": timestamp,
|
||||||
|
"severity": "critical"
|
||||||
|
})
|
||||||
|
|
||||||
|
# 5. بدء النسخ الاحتياطي الطارئ
|
||||||
|
subprocess.run([
|
||||||
|
"ghaymah", "backup", "create",
|
||||||
|
"--emergency",
|
||||||
|
"--source", "prod-data",
|
||||||
|
"--destination", "emergency-backups"
|
||||||
|
])
|
||||||
|
|
||||||
|
def send_alert(alert: dict):
|
||||||
|
"""إرسال تنبيه للفريق"""
|
||||||
|
webhook_url = os.environ.get("ALERT_WEBHOOK")
|
||||||
|
requests.post(webhook_url, json=alert)
|
||||||
|
```
|
||||||
|
|
||||||
|
### ب. Immutable Backups (نسخ احتياطية غير قابلة للتعديل)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# تكوين النسخ الاحتياطية غير القابلة للتعديل
|
||||||
|
immutable_backup:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# فترة عدم القابلية للتعديل
|
||||||
|
retention_lock:
|
||||||
|
min_days: 7
|
||||||
|
max_days: 365
|
||||||
|
|
||||||
|
# حماية من الحذف
|
||||||
|
deletion_protection:
|
||||||
|
enabled: true
|
||||||
|
require_mfa: true
|
||||||
|
require_approval: 2 # موافقة شخصين
|
||||||
|
cooling_period: 72h # فترة انتظار قبل الحذف
|
||||||
|
|
||||||
|
# التشفير
|
||||||
|
encryption:
|
||||||
|
algorithm: AES-256-GCM
|
||||||
|
key_management: customer_managed
|
||||||
|
key_rotation: 90d
|
||||||
|
```
|
||||||
|
|
||||||
|
**التنفيذ:**
|
||||||
|
```bash
|
||||||
|
# إنشاء bucket مع حماية WORM
|
||||||
|
ghaymah storage bucket create secure-backups \
|
||||||
|
--worm-enabled \
|
||||||
|
--retention-days 30 \
|
||||||
|
--deletion-protection \
|
||||||
|
--require-mfa-delete
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. طبقة الاستعادة (Recovery)
|
||||||
|
|
||||||
|
### أ. خطة استمرارية الأعمال
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
business_continuity:
|
||||||
|
# أولوية الاستعادة
|
||||||
|
recovery_priority:
|
||||||
|
tier_1: # أول 4 ساعات
|
||||||
|
- name: "قاعدة البيانات الرئيسية"
|
||||||
|
rto: 1h
|
||||||
|
- name: "API الأساسي"
|
||||||
|
rto: 2h
|
||||||
|
|
||||||
|
tier_2: # 4-8 ساعات
|
||||||
|
- name: "واجهة المستخدم"
|
||||||
|
rto: 4h
|
||||||
|
- name: "خدمات الدفع"
|
||||||
|
rto: 4h
|
||||||
|
|
||||||
|
tier_3: # 8-24 ساعة
|
||||||
|
- name: "التقارير"
|
||||||
|
rto: 12h
|
||||||
|
- name: "الأرشيف"
|
||||||
|
rto: 24h
|
||||||
|
|
||||||
|
# موقع الاستعادة البديل
|
||||||
|
dr_site:
|
||||||
|
location: me-jeddah-1
|
||||||
|
sync_frequency: hourly
|
||||||
|
failover_time: 30m
|
||||||
|
```
|
||||||
|
|
||||||
|
### ب. Runbook الاستعادة
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Runbook: استعادة من Ransomware
|
||||||
|
|
||||||
|
### المتطلبات المسبقة
|
||||||
|
- [ ] تأكيد عزل الأنظمة المتأثرة
|
||||||
|
- [ ] تحديد آخر نسخة احتياطية سليمة
|
||||||
|
- [ ] تجهيز بيئة الاستعادة
|
||||||
|
|
||||||
|
### خطوات الاستعادة
|
||||||
|
|
||||||
|
1. **إنشاء بيئة نظيفة**
|
||||||
|
```bash
|
||||||
|
ghaymah project create recovery-env --from-template secure-base
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **استعادة قاعدة البيانات**
|
||||||
|
```bash
|
||||||
|
ghaymah backup restore \
|
||||||
|
--source secure-backups/db-latest \
|
||||||
|
--destination recovery-env/database \
|
||||||
|
--verify
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **استعادة الملفات**
|
||||||
|
```bash
|
||||||
|
ghaymah backup restore \
|
||||||
|
--source secure-backups/files-latest \
|
||||||
|
--destination recovery-env/storage \
|
||||||
|
--verify
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **اختبار الخدمات**
|
||||||
|
```bash
|
||||||
|
ghaymah test run --suite smoke-test --project recovery-env
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **تبديل DNS**
|
||||||
|
```bash
|
||||||
|
ghaymah dns update \
|
||||||
|
--domain app.example.com \
|
||||||
|
--target recovery-env
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. التدريب والتوعية
|
||||||
|
|
||||||
|
### برنامج التدريب
|
||||||
|
|
||||||
|
| الفئة | التدريب | التكرار |
|
||||||
|
|-------|---------|---------|
|
||||||
|
| جميع الموظفين | التوعية بالتصيد | ربع سنوي |
|
||||||
|
| فريق IT | الاستجابة للحوادث | شهري |
|
||||||
|
| المطورين | البرمجة الآمنة | ربع سنوي |
|
||||||
|
| الإدارة | إدارة الأزمات | نصف سنوي |
|
||||||
|
|
||||||
|
### محاكاة الهجمات
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# جدول تمارين المحاكاة
|
||||||
|
simulation_exercises:
|
||||||
|
- name: "تمرين Ransomware"
|
||||||
|
frequency: quarterly
|
||||||
|
scope: full_organization
|
||||||
|
objectives:
|
||||||
|
- اختبار خطة الاستجابة
|
||||||
|
- قياس وقت الاكتشاف
|
||||||
|
- اختبار الاستعادة
|
||||||
|
|
||||||
|
- name: "اختبار التصيد"
|
||||||
|
frequency: monthly
|
||||||
|
scope: random_sample
|
||||||
|
objectives:
|
||||||
|
- قياس الوعي
|
||||||
|
- تحديد نقاط الضعف
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. ملخص خطة الوقاية
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ ملخص خطة الوقاية الشاملة │
|
||||||
|
├─────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ 🛡️ الوقاية: │
|
||||||
|
│ ✓ MFA إجباري لجميع الحسابات │
|
||||||
|
│ ✓ تقسيم الشبكة وعزل النسخ الاحتياطية │
|
||||||
|
│ ✓ تحديثات أمنية تلقائية │
|
||||||
|
│ ✓ سياسة أقل صلاحية │
|
||||||
|
│ │
|
||||||
|
│ 🔍 الكشف: │
|
||||||
|
│ ✓ SIEM مع قواعد كشف Ransomware │
|
||||||
|
│ ✓ مراقبة سلامة الملفات (FIM) │
|
||||||
|
│ ✓ تنبيهات فورية │
|
||||||
|
│ │
|
||||||
|
│ 🚧 الاحتواء: │
|
||||||
|
│ ✓ عزل تلقائي عند الكشف │
|
||||||
|
│ ✓ نسخ احتياطية غير قابلة للتعديل (WORM) │
|
||||||
|
│ ✓ وضع القراءة فقط للتخزين │
|
||||||
|
│ │
|
||||||
|
│ 🔄 الاستعادة: │
|
||||||
|
│ ✓ قاعدة 3-2-1 للنسخ الاحتياطي │
|
||||||
|
│ ✓ RPO: 1 ساعة | RTO: 4 ساعات │
|
||||||
|
│ ✓ اختبار استعادة دوري │
|
||||||
|
│ │
|
||||||
|
│ 📚 التدريب: │
|
||||||
|
│ ✓ توعية ربع سنوية │
|
||||||
|
│ ✓ محاكاة هجمات │
|
||||||
|
│ ✓ تمارين استجابة للحوادث │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. قائمة التحقق النهائية
|
||||||
|
|
||||||
|
### أسبوعياً
|
||||||
|
- ✅ مراجعة تنبيهات SIEM
|
||||||
|
- ✅ التحقق من نجاح النسخ الاحتياطي
|
||||||
|
- ✅ فحص تحديثات الأمان
|
||||||
|
|
||||||
|
### شهرياً
|
||||||
|
- ✅ اختبار استعادة عشوائي
|
||||||
|
- ✅ مراجعة صلاحيات المستخدمين
|
||||||
|
- ✅ تحديث قواعد الكشف
|
||||||
|
|
||||||
|
### ربع سنوياً
|
||||||
|
- ✅ تمرين محاكاة Ransomware
|
||||||
|
- ✅ مراجعة خطة الاستجابة
|
||||||
|
- ✅ تدريب الموظفين
|
||||||
|
|
||||||
|
### سنوياً
|
||||||
|
- ✅ تدقيق أمني شامل
|
||||||
|
- ✅ تحديث خطة استمرارية الأعمال
|
||||||
|
- ✅ مراجعة العقود مع المزودين
|
||||||
Reference in New Issue
Block a user