# 🎣 Phishing Simulator (Laravel)

Plateforme interne de **simulation de phishing** pour tester et améliorer la vigilance
des employés. Migration/refonte de l'ancien prototype Spring Boot (`../`) vers
**Laravel 13 + Blade**, déployable via **Docker (MySQL)**.

> ⚠️ **Usage autorisé uniquement.** Cet outil est destiné à des campagnes de
> sensibilisation **internes**, sur des employés de votre propre organisation, avec
> l'accord de la direction / RH. Ne l'utilisez jamais contre des tiers.

---

## Fonctionnalités

- **Employés** : gestion de la liste des cibles (nom, email, département).
- **Campagnes** : sujet, expéditeur, template HTML personnalisable.
- **Pièges multiples par mail** : lien texte, bouton, image cliquable. Tous les pièges
  d'une campagne pointent vers **une seule URL cachée commune** (`landing_url`), mais
  chaque clic est **attribué au piège précis** qui a été cliqué.
- **Personnalisation HTML** : placeholders `{{name}}`, `{{email}}`, `{{department}}`.
- **Tracking** :
  - clic par piège (token unique par destinataire, **non devinable**),
  - ouverture du mail (pixel invisible),
  - horodatage, IP et user-agent de chaque événement.
- **Tableau de bord** : taux d'ouverture / de clic par campagne, top des « récidivistes ».
- **Page de sensibilisation** intégrée affichée après un clic (si aucune URL externe).
- **Export CSV** par campagne.
- **Console d'admin protégée** par mot de passe (`ADMIN_PASSWORD`).

---

## Placeholders du template mail

| Placeholder        | Rôle                                                        |
|--------------------|-------------------------------------------------------------|
| `{{name}}`         | Nom de l'employé                                            |
| `{{email}}`        | Email de l'employé                                          |
| `{{department}}`   | Département                                                 |
| `{{trap:1}}` …     | Insère le Nᵉ piège (rendu = lien/bouton/image tracké)       |
| `{{pixel}}`        | Pixel d'ouverture (ajouté automatiquement si absent)        |

Un piège défini mais non placé explicitement dans le HTML est **ajouté en bas** du mail
(jamais perdu).

---

## Démarrage rapide (Docker)

```bash
cp .env.example .env
php artisan key:generate            # ou laissez l'entrypoint le faire
# éditez .env : ADMIN_PASSWORD, MAIL_*, APP_URL (domaine réel en prod)
docker compose up -d --build
```

- Console admin : http://localhost:8000
- Adminer (DB) : http://localhost:8081  (serveur `db`, user/pass = `.env`)

L'entrypoint attend MySQL, exécute `php artisan migrate --force`, puis (si
`SEED_ON_DEPLOY=true`) charge les données initiales via le seeder.

### Données de production en SQL

Le schéma est géré par les **migrations Laravel**. Les données initiales (employés)
sont fournies en SQL idempotent dans [`database/sql/employees.sql`](database/sql/employees.sql) :

```bash
docker compose exec -T db mysql -uphishing -psecret phishing < database/sql/employees.sql
```

---

## Développement local (sans Docker)

```bash
composer install
cp .env.example .env && php artisan key:generate
# configurez une base MySQL locale dans .env
php artisan migrate --seed
php artisan serve
php artisan test          # tests de bout en bout
```

---

## Configuration importante

| Variable          | Description                                                        |
|-------------------|--------------------------------------------------------------------|
| `APP_URL`         | **Doit** être l'URL publiquement joignable (les liens des mails en dérivent). |
| `ADMIN_PASSWORD`  | Mot de passe de la console d'admin.                                |
| `MAIL_*`          | SMTP d'envoi. **Jamais** de secret en dur dans le code.            |
| `SEED_ON_DEPLOY`  | `true` pour charger les données initiales au démarrage.            |

---

## Améliorations apportées vs. le prototype Spring

1. **Tokens non devinables** par destinataire au lieu de l'ID séquentiel `/{id}`
   (l'ancien `/1`, `/2`… était énumérable par n'importe qui).
2. **Attribution par piège** : on sait *quel* appât a fonctionné, pas juste « un clic ».
3. **Tracking d'ouverture** séparé du clic (pixel invisible).
4. **Métadonnées d'événement** : horodatage, IP, user-agent.
5. **Tableau de bord** avec taux d'ouverture/clic et récidivistes (au lieu d'un CSV par mail).
6. **Page de sensibilisation** éducative post-clic — le vrai objectif d'une campagne.
7. **Secrets hors du code** (variables d'environnement, `.env` non commité) — l'ancien
   code contenait des mots de passe SMTP en clair.
8. **Console protégée** par mot de passe.
9. **Personnalisation** riche via placeholders.
10. **Tests automatisés** de bout en bout.

### Pistes futures

- File d'attente (`queue:work`) pour l'envoi de gros volumes sans bloquer la requête.
- Planification d'envoi (date/heure) + envoi échelonné.
- Rôles/comptes admin multiples (auth Laravel complète).
- Templates réutilisables et bibliothèque d'appâts.
- Rapport PDF exportable, et lien vers un module de formation après échec.
- Webhook/notification (Slack, Teams) au lieu d'un mail par clic.

---

## Réglages SMTP (interface)

La configuration d'envoi se fait dans **Réglages** (menu du haut) plutôt que dans `.env` :
hôte, port, chiffrement (SSL/TLS 465 ou STARTTLS 587), utilisateur, mot de passe
(**chiffré en base**), expéditeur par défaut. Un bouton **« Tester l'envoi »** permet de
valider la config immédiatement. Ces valeurs priment sur `.env` ; si la table `settings`
est vide, `.env` sert de fallback.

## Tableau de bord / monitoring

Le dashboard affiche des graphiques (Chart.js, servi **en local** — aucun CDN requis) :
courbe des ouvertures/clics sur 14 jours, entonnoir global (envoyés → ouverts → cliqués),
et barres par campagne, en plus des compteurs et du top des récidivistes.

## Délivrabilité / éviter le spam

Pour qu'un mail arrive en boîte de réception (et non en spam) :

1. **DKIM** — active la signature DKIM du domaine expéditeur dans l'espace OVH, puis
   publie l'enregistrement DNS fourni. **C'est le facteur le plus important.**
2. **DMARC** — ajoute `_dmarc.<domaine> TXT "v=DMARC1; p=none; rua=mailto:postmaster@<domaine>"`.
3. **SPF** — déjà présent pour `9albi.me` (`v=spf1 include:mx.ovh.com -all`).
4. **Expéditeur aligné** : le `From` doit être une adresse **du domaine authentifié**.
5. **Contenu** : éviter l'imitation de marques (Microsoft…), les mots déclencheurs
   (« compte suspendu »), les mails tout-image. Une **version texte** est désormais
   jointe automatiquement à chaque envoi (fait côté app).
6. **Volume** : envoyer progressivement depuis une IP/domaine « réchauffés ».

> Note : OVH mutualisé filtre parfois le contenu de type phishing en sortie (accepté en
> 250 puis jeté). Pour de vraies campagnes, un domaine dédié avec DKIM/DMARC est recommandé.
