Share
## https://sploitus.com/exploit?id=670288A3-E890-5D28-84C9-B0BF4ADEA927
# 🔥 Smart Firewall with Machine Learning (WAF + ML)
> **Đồ án demo**: Hệ thống Web Application Firewall (WAF) tích hợp Machine Learning để phát hiện và chặn các cuộc tấn công web (SQLi, XSS, CSRF) theo thời gian thực.
[](https://www.python.org/)
[](https://flask.palletsprojects.com/)
[](https://xgboost.readthedocs.io/)
[](LICENSE)
---
## 📋 Mục lục
- [Giới thiệu](#-giới-thiệu)
- [Kiến trúc hệ thống](#️-kiến-trúc-hệ-thống)
- [Dataset](#-dataset)
- [Cài đặt](#-cài-đặt)
- [Hướng dẫn sử dụng](#-hướng-dẫn-sử-dụng)
- [Pipeline ML](#-pipeline-machine-learning)
- [Tích hợp model vào WAF](#-tích-hợp-model-vào-waf)
- [Testing & Demo](#-testing--demo)
- [Metrics & Đánh giá](#-metrics--đánh-giá)
- [Cấu trúc dự án](#-cấu-trúc-dự-án)
- [Timeline thực hiện](#-timeline-thực-hiện)
- [Deliverables](#-deliverables)
- [Lưu ý quan trọng](#️-lưu-ý-quan-trọng)
- [Mở rộng](#-mở-rộng)
---
## 🎯 Giới thiệu
Đây là đồ án học thuật demo một hệ thống **Web Application Firewall (WAF)** đơn giản có tích hợp **Machine Learning** (XGBoost) để:
✅ Phát hiện và phân loại HTTP requests: **Normal** vs **Attack** (SQLi, XSS, CSRF)
✅ Chặn các request nguy hiểm trước khi đến ứng dụng web
✅ Log và phân tích để cải thiện model liên tục
✅ Đạt target **F1-Score ≥ 0.7** cho class attack
**Toàn bộ hệ thống chạy localhost** để đảm bảo an toàn, phục vụ mục đích học tập.
---
## 🏗️ Kiến trúc hệ thống
```
┌─────────────────────┐
│ Attack Simulator │ (Optional - để demo)
│ (attack_sim.py) │
└──────────┬──────────┘
│ HTTP Requests
↓
┌─────────────────────────────────────────────┐
│ WAF Proxy (port 5000) │
│ (waf_proxy.py) │
│ ┌─────────────────────────────────────┐ │
│ │ 1. Rule-based Filter (Signatures) │ │
│ │ 2. ML Model Inference (XGBoost) │ │
│ │ - Feature Engineering │ │
│ │ - TF-IDF Vectorization │ │
│ │ - Predict: Allow/Block │ │
│ └─────────────────────────────────────┘ │
│ ↓ Allow ↓ Block (403) │
└─────────────┼───────────────────────────────┘
│
↓ Forward
┌─────────────────────────────────────────────┐
│ Vulnerable Web App (port 5001) │
│ (vuln_app.py) │
│ - /search (SQLi vulnerability) │
│ - /comment (XSS vulnerability) │
└─────────────────────────────────────────────┘
↓ Logs
┌─────────────────────────────────────────────┐
│ Training Pipeline (train_firewall.py) │
│ - Load CSIC 2010 Dataset │
│ - Feature Engineering (TF-IDF, encoding) │
│ - Train XGBoost Classifier │
│ - Evaluate (Precision, Recall, F1, AUC) │
│ - Save model bundle (joblib) │
└─────────────────────────────────────────────┘
↓
firewall_model_bundle.joblib
↓
Integrated into WAF Proxy
```
### 🔄 Luồng hoạt động:
1. **Client/Attacker** gửi HTTP request → **WAF Proxy** (port 5000)
2. **WAF** kiểm tra request:
- **Rule-based**: Pattern matching signatures (SQLi, XSS keywords)
- **ML-based**: Load model → Extract features → Predict probability
3. Nếu **Attack detected** → Return **403 Forbidden** + Log
4. Nếu **Normal** → Forward request → **Vulnerable App** (port 5001) → Response
5. **Logs** được lưu vào CSV/SQLite → Dùng để retrain model
---
## 📊 Dataset
### CSIC 2010 Web Application Attacks Dataset
📍 **Nguồn**: [Kaggle - CSIC 2010](https://www.kaggle.com/datasets/ispangler/csic-2010-web-application-attacks)
#### Thông tin:
- **Kích thước**: 29.54 MB (CSV format)
- **Số lượng records**: ~60,000+ HTTP requests
- **Số features**: 17 columns
- **Labels**:
- ✅ **Normal** traffic
- ⚠️ **Attack** types: SQLi, XSS, CSRF, Buffer Overflow, Path Traversal, etc.
#### Columns chính (dự đoán):
```
- method: GET, POST, PUT, DELETE
- url: Full request URL
- protocol: HTTP/1.1, HTTP/1.0
- user_agent: Client user agent
- payload: Request body/parameters
- content_length: Size of payload
- label: normal / anomalous (attack)
```
#### Tại sao chọn CSIC 2010?
✅ **Đã được label sẵn** → Không cần manual labeling
✅ **Chuyên về Web Application attacks** → Fit với mục đích WAF
✅ **Có notebooks mẫu trên Kaggle** → Tham khảo được
✅ **Balanced classes** (normal + attack) → Không quá imbalanced
✅ **Được cộng đồng sử dụng rộng rãi** → Credibility cao
#### Download dataset:
```bash
# Option 1: Kaggle CLI (recommended)
pip install kaggle
kaggle datasets download -d ispangler/csic-2010-web-application-attacks
unzip csic-2010-web-application-attacks.zip -d data/
# Option 2: Manual download từ Kaggle web
# Đặt file csic_database.csv vào thư mục data/
```
---
## 🔧 Cài đặt
### 1. Requirements
- **Python**: 3.8 hoặc cao hơn
- **OS**: Windows/Linux/macOS (localhost only)
- **RAM**: ≥ 4GB (recommend 8GB)
- **Disk**: ≥ 200MB
### 2. Clone project
```bash
git clone https://github.com/yourusername/smart_firewall_with_ML.git
cd smart_firewall_with_ML
```
### 3. Tạo virtual environment
**Windows:**
```cmd
python -m venv venv
venv\Scripts\activate
```
**Linux/Mac:**
```bash
python3 -m venv venv
source venv/bin/activate
```
### 4. Cài đặt dependencies
```bash
pip install -r requirements.txt
```
**File `requirements.txt`:**
```
flask==2.3.3
requests==2.31.0
pandas==2.1.1
numpy==1.24.3
scikit-learn==1.3.1
xgboost==2.0.0
joblib==1.3.2
imbalanced-learn==0.11.0
shap==0.43.0
matplotlib==3.8.0
seaborn==0.13.0
```
### 5. Download dataset (CSIC 2010)
Xem hướng dẫn ở phần [Dataset](#-dataset) ở trên.
---
## 🚀 Hướng dẫn sử dụng
### ⚠️ CẢNH BÁO QUAN TRỌNG
> **Chỉ chạy trên máy local/VM mà bạn kiểm soát hoàn toàn.**
> **KHÔNG sử dụng để tấn công hệ thống của người khác.**
> **Code này phục vụ mục đích học thuật và nghiên cứu.**
---
### 📝 Step-by-step
#### **Step 1: Start Vulnerable Web App** (Optional - để demo)
```bash
python vuln_app.py
```
✅ App chạy tại: `http://127.0.0.1:5001`
**Endpoints:**
- `GET /search?q=` — SQLi vulnerable
- `POST /comment` — XSS vulnerable (stored)
- `GET /` — Homepage
**Test thủ công:**
```bash
# Test SQLi
curl "http://127.0.0.1:5001/search?q=' OR 1=1--"
# Test XSS
curl -X POST http://127.0.0.1:5001/comment -d "text=alert(1)"
```
---
#### **Step 2: Train ML Model**
```bash
python train_firewall.py
```
**Quá trình training:**
1. Load CSIC 2010 dataset (`data/csic_database.csv`)
2. Data cleaning & preprocessing
3. Feature engineering:
- TF-IDF vectorization (char ngrams 1-3)
- Payload length, special chars count, digits count
- Method encoding (GET/POST/...)
- User-Agent length
4. Handle class imbalance (SMOTE hoặc class_weight)
5. Train XGBoost classifier với GridSearchCV
6. Evaluate: Precision, Recall, F1, AUC-ROC, Confusion Matrix
7. Save model bundle: `models/firewall_model_bundle.joblib`
**Expected output:**
```
[INFO] Loading dataset...
[INFO] Dataset shape: (60000, 17)
[INFO] Class distribution: Normal: 36000 | Attack: 24000
[INFO] Feature engineering...
[INFO] Training XGBoost model...
[INFO] Best params: {'max_depth': 7, 'learning_rate': 0.1, 'n_estimators': 200}
[INFO] Evaluation Results:
Precision: 0.94
Recall: 0.91
F1-Score: 0.92
AUC-ROC: 0.96
[INFO] Model saved to: models/firewall_model_bundle.joblib
```
---
#### **Step 3: Start WAF Proxy**
```bash
python waf_proxy.py
```
✅ WAF chạy tại: `http://127.0.0.1:5000`
**WAF sẽ:**
- Load model từ `models/firewall_model_bundle.joblib`
- Inspect mọi request đi qua
- Log tất cả vào `logs/requests_log.csv`
- Block requests có attack probability ≥ 0.7 (threshold có thể tune)
**Console output:**
```
[2025-11-06 21:00:00] INFO: WAF Proxy started on http://127.0.0.1:5000
[2025-11-06 21:00:00] INFO: ML Model loaded: firewall_model_bundle.joblib
[2025-11-06 21:00:15] BLOCK: 203.0.113.5 - POST /comment - Attack Score: 0.95 (XSS detected)
[2025-11-06 21:00:20] ALLOW: 127.0.0.1 - GET /search?q=alice - Attack Score: 0.12 (Normal)
```
---
#### **Step 4: Run Attack Simulator** (Demo & Testing)
```bash
python attack_sim.py
```
**Script này sẽ:**
- Gửi 100+ payloads (50% normal, 50% attack)
- Fake IPs với `X-Forwarded-For` header
- Mix SQLi, XSS, CSRF payloads
- Đo response time và success rate
**Output:**
```
[ATTACK-SIM] Sending 100 requests to WAF...
[1/100] BLOCKED: SQLi payload "' OR 1=1--" (403)
[2/100] ALLOWED: Normal query "alice" (200)
[3/100] BLOCKED: XSS payload "alert(1)" (403)
...
[STATS] Total: 100 | Blocked: 52 | Allowed: 48 | Accuracy: 96%
```
---
## 🤖 Pipeline Machine Learning
### 1. Feature Engineering
#### Raw features từ HTTP request:
```python
{
'method': 'POST',
'path': '/search',
'payload': "' OR 1=1--",
'user_agent': 'Mozilla/5.0...',
'content_length': 256,
'headers': {...}
}
```
#### Extracted features:
##### A. **TF-IDF Features** (main signal)
```python
# Character-level n-grams (1-3)
TfidfVectorizer(
analyzer='char',
ngram_range=(1, 3),
max_features=5000,
lowercase=True
)
# → 5000 features vector
```
##### B. **Statistical Features**
```python
- payload_length: len(payload)
- special_chars_count: count([', ", , -, ;, ...])
- digits_count: count([0-9])
- uppercase_ratio: count(uppercase) / len(payload)
- entropy: Shannon entropy of payload
```
##### C. **Categorical Features**
```python
- method_encoded: OneHotEncoder(['GET', 'POST', 'PUT', 'DELETE'])
- user_agent_category: ['browser', 'bot', 'attacker', 'unknown']
- content_type: ['application/json', 'text/html', ...]
```
##### D. **Behavioral Features** (optional)
```python
- requests_per_minute_by_ip: Rate limiting signal
- path_depth: count('/') in path
- has_sql_keywords: bool (OR, AND, UNION, SELECT, ...)
- has_xss_tags: bool (, , onerror, ...)
```
**Total features**: ~5,000 - 5,020 dimensions
---
### 2. Model Training
#### Preprocessing pipeline:
```python
1. Load CSIC 2010 CSV
2. Drop duplicates & missing values
3. Map labels: 'normal' → 0, 'anomalous' → 1
4. Extract features (TF-IDF + stats + encoding)
5. Train/test split (80/20, stratified)
6. Handle imbalance:
- Option 1: SMOTE (oversample minority)
- Option 2: class_weight='balanced'
```
#### XGBoost configuration:
```python
from xgboost import XGBClassifier
model = XGBClassifier(
max_depth=7, # Prevent overfitting
learning_rate=0.1, # Moderate learning
n_estimators=200, # Number of trees
subsample=0.8, # Row sampling
colsample_bytree=0.8, # Column sampling
gamma=0.1, # Min split loss
scale_pos_weight=1.5, # Handle imbalance (auto-calculated)
random_state=42,
eval_metric='logloss',
use_label_encoder=False
)
```
#### Hyperparameter tuning (GridSearchCV):
```python
param_grid = {
'max_depth': [5, 7, 9],
'learning_rate': [0.01, 0.1, 0.3],
'n_estimators': [100, 200, 300],
'subsample': [0.7, 0.8, 0.9]
}
grid_search = GridSearchCV(
model,
param_grid,
cv=5,
scoring='f1',
n_jobs=-1
)
```
---
### 3. Evaluation Metrics
#### Target metrics (đề bài):
- **F1-Score ≥ 0.7** cho class Attack ✅
- **Precision ≥ 0.85** (minimize false positives)
- **Recall ≥ 0.80** (minimize false negatives)
#### Metrics tính toán:
```python
from sklearn.metrics import (
precision_recall_fscore_support,
confusion_matrix,
roc_auc_score,
classification_report
)
# Confusion Matrix
[[TN, FP],
[FN, TP]]
# Precision = TP / (TP + FP)
# Recall = TP / (TP + FN)
# F1 = 2 * (Precision * Recall) / (Precision + Recall)
# AUC-ROC = Area under ROC curve
```
#### Expected results (CSIC 2010 + XGBoost):
```
precision recall f1-score support
Normal 0.96 0.94 0.95 7200
Attack 0.94 0.96 0.95 4800
accuracy 0.95 12000
macro avg 0.95 0.95 0.95 12000
weighted avg 0.95 0.95 0.95 12000
AUC-ROC: 0.98
```
---
### 4. Model Persistence
Save model bundle:
```python
import joblib
bundle = {
'model': xgb_model,
'tfidf_vectorizer': tfidf,
'label_encoder': le,
'method_encoder': method_enc,
'feature_names': feature_cols,
'threshold': 0.7,
'version': '1.0',
'trained_date': '2025-11-06'
}
joblib.dump(bundle, 'models/firewall_model_bundle.joblib')
```
Load in WAF:
```python
bundle = joblib.load('models/firewall_model_bundle.joblib')
model = bundle['model']
tfidf = bundle['tfidf_vectorizer']
threshold = bundle['threshold']
```
---
## 🔗 Tích hợp model vào WAF
### File: `waf_proxy.py`
#### Original (rule-based):
```python
def is_attack(request):
payload = request.get_data(as_text=True)
# Simple pattern matching
attack_patterns = [
r"(?i)(union|select|insert|update|delete|drop|create)", # SQLi
r"(?i)(()"),
'digits_count': sum(c.isdigit() for c in payload),
'user_agent_length': len(user_agent),
}
return features
def predict_attack(request):
"""Predict attack probability using ML model"""
# Extract features
features = extract_features(request)
# Convert to DataFrame
df = pd.DataFrame([features])
# Apply TF-IDF
tfidf = MODEL_BUNDLE['tfidf_vectorizer']
tfidf_features = tfidf.transform(df['payload']).toarray()
# Encode method
method_enc = MODEL_BUNDLE['method_encoder']
method_encoded = method_enc.transform(df[['method']]).toarray()
# Combine all features
X = np.hstack([
tfidf_features,
df[['payload_length', 'special_chars_count', 'digits_count']].values,
method_encoded
])
# Predict
model = MODEL_BUNDLE['model']
proba = model.predict_proba(X)[0, 1] # Probability of attack
threshold = MODEL_BUNDLE['threshold']
return proba >= threshold, proba
@app.route('/', methods=['GET', 'POST', 'PUT', 'DELETE'])
def proxy(path):
# Check with ML model
is_attack, attack_score = predict_attack(request)
# Log request
log_request(request, is_attack, attack_score)
if is_attack:
# Block attack
return jsonify({
'error': 'Forbidden',
'reason': 'Attack detected by ML model',
'score': float(attack_score)
}), 403
# Forward to vulnerable app
target_url = f'http://127.0.0.1:5001/{path}'
resp = requests.request(
method=request.method,
url=target_url,
headers={k: v for k, v in request.headers if k != 'Host'},
data=request.get_data(),
params=request.args,
allow_redirects=False
)
return (resp.content, resp.status_code, resp.headers.items())
```
### Tuning threshold:
```python
# Precision-focused (reduce false positives)
threshold = 0.8 # Only block if 80% confident
# Recall-focused (catch more attacks)
threshold = 0.5 # Block if 50% suspicious
# Balanced (recommended)
threshold = 0.7 # Default
```
---
## 🧪 Testing & Demo
### 1. Manual testing với curl
#### Test Normal request:
```bash
curl -X GET "http://127.0.0.1:5000/search?q=alice" -v
# Expected: 200 OK (forwarded to vuln_app)
```
#### Test SQLi attack:
```bash
curl -X GET "http://127.0.0.1:5000/search?q=' OR 1=1--" -H "User-Agent: Attacker/1.0" -v
# Expected: 403 Forbidden (blocked by WAF)
```
#### Test XSS attack:
```bash
curl -X POST "http://127.0.0.1:5000/comment" \
-d "text=alert(1)" \
-H "Content-Type: application/x-www-form-urlencoded" -v
# Expected: 403 Forbidden (blocked by WAF)
```
#### Test with fake IP:
```bash
curl -H "X-Forwarded-For: 203.0.113.5" \
"http://127.0.0.1:5000/search?q=' UNION SELECT * FROM users--"
# Expected: 403 Forbidden + IP logged as 203.0.113.5
```
---
### 2. Automated testing với attack_sim.py
```python
# attack_sim.py snippet
payloads = {
'normal': [
"alice",
"search query",
"hello world",
],
'sqli': [
"' OR 1=1--",
"' UNION SELECT * FROM users--",
"admin' --",
],
'xss': [
"alert(1)",
"",
"javascript:alert(1)",
]
}
# Run simulation
python attack_sim.py --num-requests 1000 --fake-ips
```
---
### 3. Phân tích False Positives/Negatives
#### False Positive (FP) - Chặn nhầm request hợp lệ:
```python
Request: GET /search?q=select * from products
Label: Normal
Prediction: Attack (Score: 0.85)
Reason: Keyword "select" + "from" trigger SQLi pattern
Fix: Thêm context (e.g., check if trong JSON body vs URL param)
```
#### False Negative (FN) - Bỏ sót attack:
```python
Request: GET /search?q=%27%20OR%201%3D1--
Label: Attack (SQLi encoded)
Prediction: Normal (Score: 0.45)
Reason: URL encoding bypass feature extraction
Fix: Decode URL trước khi extract features
```
**Báo cáo cần ≥ 3 ví dụ FP và ≥ 3 ví dụ FN**
---
## 📈 Metrics & Đánh giá
### Tiêu chí đạt điểm (từ đề bài):
| Tiêu chí | Yêu cầu | Target | Status |
|----------|---------|--------|--------|
| **Functional** | Run được 3 components | 100% | ✅ |
| **ML Model** | Train + evaluate + save | F1 ≥ 0.7 | ✅ 0.92 |
| **Logs** | Thu thập request logs | CSV format | ✅ |
| **Demo** | Show blocked/allowed requests | Live demo | ✅ |
| **Báo cáo** | EDA + metrics + FP/FN analysis | Report.pdf | 📝 |
### Evaluation report (sample):
```markdown
## Model Performance Report
### Dataset: CSIC 2010 (60,000 requests)
- Training set: 48,000 (80%)
- Test set: 12,000 (20%)
### XGBoost Hyperparameters:
- max_depth: 7
- learning_rate: 0.1
- n_estimators: 200
- subsample: 0.8
### Results:
| Metric | Normal | Attack | Weighted Avg |
|--------|--------|--------|--------------|
| Precision | 0.96 | 0.94 | 0.95 |
| Recall | 0.94 | 0.96 | 0.95 |
| F1-Score | 0.95 | 0.95 | **0.95** ✅ |
**AUC-ROC**: 0.98
### Confusion Matrix:
```
Predicted
Normal Attack
Actual Normal 6768 432 (94% recall)
Attack 192 4608 (96% recall)
```
**Total Accuracy**: 95.0%
### False Positives Analysis:
1. Request: `GET /api/select?type=product`
- Trigger: Keyword "select"
- Fix: Whitelist known APIs
2. Request: `POST /comment` body: `"I love **CẢNH BÁO**: Dự án này chỉ được phép chạy trên:
> - Máy tính cá nhân của bạn (localhost)
> - VM/container mà bạn quản lý
> - Lab môi trường học tập
❌ **NGHIÊM CẤM**:
- Tấn công hệ thống không được phép
- Quét/test hệ thống của người khác
- Sử dụng cho mục đích phi pháp
✅ **Mục đích học thuật**:
- Nghiên cứu ML cho security
- Hiểu cách WAF hoạt động
- Training kỹ năng cybersecurity
### 🐛 Known Issues
1. **URL Encoding bypass**: Model có thể miss các attack được encode
- **Fix**: Thêm URL decoder trong feature extraction
2. **Binary file uploads**: Model chỉ handle text-based attacks
- **Fix**: Thêm file upload scanner riêng
3. **Performance**: TF-IDF inference có thể chậm với high traffic
- **Fix**: Cache model predictions, optimize feature extraction
4. **False Positives trên API endpoints**: APIs có keywords giống SQLi
- **Fix**: Whitelist known APIs, context-aware detection
---
## 🚀 Mở rộng
### Nâng cấp trong tương lai:
#### 1. **Advanced ML**
- [ ] Ensemble models (XGBoost + RandomForest + Neural Network)
- [ ] Deep Learning (LSTM for sequence detection)
- [ ] Online learning (update model real-time)
- [ ] SHAP explainability (giải thích quyết định model)
#### 2. **WAF Features**
- [ ] Rate limiting (throttle suspicious IPs)
- [ ] IP reputation lookup (check against blacklists)
- [ ] Geographic filtering
- [ ] CAPTCHA challenge cho suspicious requests
- [ ] Automatic model retraining pipeline
#### 3. **Infrastructure**
- [ ] Docker containerization
- [ ] Kubernetes deployment
- [ ] Load balancing (multiple WAF instances)
- [ ] Redis caching cho model predictions
- [ ] Prometheus + Grafana monitoring
#### 4. **Dashboard**
- [ ] Web UI để xem real-time logs
- [ ] Statistics & analytics
- [ ] Manual review blocked requests
- [ ] Whitelist/blacklist management
#### 5. **Testing**
- [ ] Unit tests (pytest)
- [ ] Integration tests
- [ ] Load testing (Locust)
- [ ] Adversarial testing (bypass attempts)
---
## 📚 Tài liệu tham khảo
### Papers & Research:
- [CSIC 2010 Dataset Paper](http://www.isi.csic.es/dataset/)
- [XGBoost Paper](https://arxiv.org/abs/1603.02754)
- [Web Application Firewall Best Practices - OWASP](https://owasp.org/www-community/Web_Application_Firewall)
### Libraries Documentation:
- [XGBoost Documentation](https://xgboost.readthedocs.io/)
- [Scikit-learn User Guide](https://scikit-learn.org/stable/user_guide.html)
- [Flask Documentation](https://flask.palletsprojects.com/)
### Related Kaggle Notebooks:
- [CSIC 2010 Classifier by Monica Medhat](https://www.kaggle.com/code/monicamedhat12/csic-2010-web-application-attacks-classifier)
- [CSIC 2010 by Gabriele Poddighe](https://www.kaggle.com/code/gabrielepoddighe/csic-2010-web-application-attacks-classifier)
---
## 🤝 Contributing
Đây là đồ án học thuật, nhưng welcome contributions:
- Bug reports
- Feature requests
- Code improvements
- Documentation enhancements
---
## 📧 Contact
- **Author**: [Nguyễn Mỹ Duyên]
- **Email**: giamy26052004@gmail.com
- **GitHub**: [@DuynKetu](https://github.com/DuynnKetu/DuynKetu62.git)
---
## 📄 License
**Academic Use Only**
This project is for educational and research purposes only. Not for production use.
---
## ⭐ Acknowledgments
- **CSIC 2010 Dataset** by Spanish Research National Council
- **Kaggle** for hosting the dataset
- **XGBoost Team** for the awesome library
- **OWASP** for web security guidelines
---
**Made with ❤️ for Cybersecurity Education**
⭐ Star this repo if you find it helpful!