Middleware Laravel passif qui détecte et journalise les injections SQL, les XSS, les RCE, les scanners de bots et plus de 175 modèles d'attaques. Doté d'un tableau de bord intégré, d'alertes Slack, d'une API REST et d'un enrichissement géographique. IDS, pas WAF.
<p align="center">
<a href="https://packagist.org/packages/jayanta/laravel-threat-detection"><img src="https://img.shields.io/packagist/v/jayanta/laravel-threat-detection.svg?style=flat-square" alt="Latest Version"></a>
<a href="https://github.com/jay123anta/laravel-threat-detection/actions/workflows/tests.yml"><img src="https://img.shields.io/github/actions/workflow/status/jay123anta/laravel-threat-detection/tests.yml?branch=main&style=flat-square&label=tests" alt="Tests"></a>
<a href="https://github.com/jay123anta/laravel-threat-detection/actions/workflows/tests.yml"><img src="https://img.shields.io/badge/PHPStan-level%205-brightgreen?style=flat-square" alt="PHPStan Level 5"></a>
<a href="https://github.com/jay123anta/laravel-threat-detection/actions/workflows/tests.yml"><img src="https://img.shields.io/badge/code%20style-Pint-orange?style=flat-square" alt="Code Style Pint"></a>
<a href="https://packagist.org/packages/jayanta/laravel-threat-detection"><img src="https://img.shields.io/packagist/dt/jayanta/laravel-threat-detection.svg?style=flat-square" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/jayanta/laravel-threat-detection"><img src="https://img.shields.io/packagist/php-v/jayanta/laravel-threat-detection?style=flat-square" alt="PHP Version"></a>
<a href="https://github.com/jay123anta/laravel-threat-detection/blob/main/LICENSE"><img src="https://img.shields.io/packagist/l/jayanta/laravel-threat-detection.svg?style=flat-square" alt="License"></a>
</p>
# Laravel Threat Detection
**Surveillance de sécurité et journalisation des attaques pour Laravel. Détectez et journalisez les injections SQL,
XSS, RCE, traversées de répertoire, scanners de bots et sondes de reconnaissance de type `/wp-admin` —
chaque requête hostile enregistrée dans votre base de données avec le contexte applicatif complet.
C'est un IDS, pas un WAF : il ne bloque, ne filtre et ne modifie jamais une requête.**
<p align="center">
<img src="https://raw.githubusercontent.com/jay123anta/laravel-threat-detection/main/art/demo.gif" alt="Installez le package, envoyez trois attaques — injection SQL, traversée de répertoire, XSS — chacune renvoie HTTP 200 car rien n'est bloqué, et les trois sont déjà comptabilisées dans threat-detection:stats" width="100%">
</p>
### Vous êtes ici parce que vous avez vu quelque chose comme ceci ?
```
GET /wp-admin/setup-config.php 404 — on a site that isn't WordPress
GET /.env 404 — someone wants your database password
GET /?id=1' UNION SELECT password FROM 200 — SQL injection against a real route
GET /phpmyadmin/index.php 404 — scanning for an admin panel
```
Ces requêtes atteignent déjà votre application Laravel. Votre journal d'accès affiche l'URL
et le code de statut, et rien d'autre — ni la charge utile décodée, ni laquelle de vos
routes a été ciblée, ni si la même IP a tenté quarante autres choses cette heure-ci.
Ce package répond à ces questions. Déposez-le dans n'importe quelle application Laravel 10–13 et il commence
à analyser chaque requête HTTP par rapport à plus de 150 motifs d'attaque, en évaluant chaque correspondance par
niveau de confiance et en l'enregistrant dans votre base de données — avec un tableau de bord intégré, des alertes Slack,
un enrichissement géographique et des exports fail2ban/liste de blocage. Aucune requête n'est jamais bloquée. Pensez
caméra de surveillance, pas verrou : il vous montre exactement qui sonde vos routes, à quelle
fréquence et avec quelles techniques.
> Extrait d'une application en production et éprouvé sur du trafic réel. Plus de 2 400 tests, aucune dépendance
> d'exécution en dehors de Laravel lui-même, et aucune connexion internet requise pour la détection.
>
> Vous effectuez une mise à niveau ? Voir [UPGRADING.md](https://github.com/jay123anta/laravel-threat-detection/blob/main/UPGRADING.md). Vous souhaitez contribuer ? Voir [CONTRIBUTING.md](https://github.com/jay123anta/laravel-threat-detection/blob/main/CONTRIBUTING.md).
## Démarrer en moins d'une minute
```bash
composer require jayanta/laravel-threat-detection
php artisan vendor:publish --tag=threat-detection-migrations
php artisan migrate
```
Ensuite, ajoutez le middleware à votre groupe `web` (une ligne dans `bootstrap/app.php` sur Laravel 11+,
ou `app/Http/Kernel.php` sur Laravel 10) — l'extrait complet se trouve dans [Quick Start](#quick-start) ci-dessous.
C'est tout ; la détection est active.
```bash
php artisan threat-detection:doctor # confirms it is actually recording
```
---
## Où cela s'inscrit : IDS vs WAF vs edge
Ce package est un **IDS passif au niveau applicatif** — il observe et enregistre, il ne
bloque pas. Il est conçu pour se placer *aux côtés* d'un WAF ou d'un service edge, et non
pour le remplacer. Chaque couche voit quelque chose que les autres ne peuvent pas voir :
| | **Ce package** (IDS applicatif) | **WAF** (ModSecurity + OWASP CRS, Cloudflare WAF) | **Edge / CDN** (Cloudflare) |
|---|:---:|:---:|:---:|
| Bloque les requêtes malveillantes | ❌ journalise uniquement | ✅ | ✅ |
| Contexte applicatif complet (URL exacte, payload décodé, utilisateur authentifié) | ✅ | ⚠️ partiel | ❌ |
| Tableau de bord intégré + journal des menaces dans votre BD | ✅ | ⚠️ variable | ⚠️ edge uniquement |
| Détections spécifiques à l'application (ex. PII Aadhaar / PAN / IFSC) | ✅ intégré + personnalisé | ⚠️ écrivez vos propres règles | ⚠️ règles personnalisées, selon le forfait |
| Fonctionne hors ligne / sans service externe | ✅ | ⚠️ dépend | ❌ |
| Arrête le trafic avant qu'il n'atteigne votre serveur | ❌ | ⚠️ WAF cloud uniquement | ✅ |
| Installation | `composer require`, migration, une ligne de middleware | moyenne–élevée | faible–moyenne |
| Coût | gratuit, MIT | variable | offre gratuite + payant |
**En résumé :** un edge/WAF est votre serrure sur la porte ; ceci est la caméra de
surveillance *à l'intérieur*, avec le contexte applicatif pour vous dire exactement ce qui
est tenté sur quelle route, par qui, et à quelle fréquence. Utilisez-le pour alimenter de
vraies décisions — bans fail2ban, limites de débit, géo-blocage — avec des données que
votre couche edge ne voit jamais.
### Ce qu'il n'est délibérément PAS
- **Pas un WAF.** Il ne bloque, ne filtre ni ne modifie jamais une requête. Utilisez
Cloudflare, mod_security ou un vrai WAF pour l'application des règles. (Pas de couche
edge à qui déléguer ? Les
[helpers côté opérateur](#acting-on-the-data-operator-side-blocking) exposent les
décisions du package pour que vous puissiez écrire votre propre middleware de blocage
en cinq lignes — le code d'application des règles reste le vôtre, pas celui du package.)
- **Pas un remplacement pour le codage sécurisé.** Les requêtes paramétrées, la validation
des entrées et l'échappement des sorties sont vos véritables défenses. Ce package
suppose que votre code est déjà sécurisé et vous donne de la *visibilité*, pas de la
protection.
- **Pas un service edge.** Si vous pouvez placer Cloudflare devant, faites-le — puis
ajoutez ceci pour le détail applicatif que les services edge ne peuvent pas voir.
- **Pas un détecteur complet, et il ne peut pas l'être.** La correspondance de motifs
attrape les attaques qui *ressemblent* à des attaques connues. Une technique inédite,
ou une technique familière suffisamment réécrite, passera sans être journalisée — et
vous ne serez pas informé qu'elle l'a fait. Le silence ici signifie « rien n'a
correspondu », jamais « rien ne s'est produit ». Là où il gagne sa place, c'est sur le
trafic à fort volume et à faible effort qui constitue l'essentiel de ce qui frappe
réellement une application Laravel publique : scanners, sondes de reconnaissance,
chaînes d'injection toutes faites, pulvérisations d'identifiants. Considérez un journal
silencieux comme une absence de preuve, et non comme la preuve d'une absence.
### Attendez-vous à ce qu'il signale votre propre contenu dès le premier jour
Une installation non réglée déclenche des alertes sur du contenu légitime, et vous devriez
le savoir avant d'installer plutôt qu'après. Ces cas sont mesurés, pas hypothétiques. Les
lignes ci-dessous sont un échantillon du plancher fixé par
[`LegitimateTrafficCorpusTest`](https://github.com/jay123anta/laravel-threat-detection/blob/main/tests/Feature/LegitimateTrafficCorpusTest.php) ;
chacune liste *tout* ce que cette requête journalise, et
[`ReadmeNoiseFloorTest`](https://github.com/jay123anta/laravel-threat-detection/blob/main/tests/Feature/ReadmeNoiseFloorTest.php) fait échouer le
build si une ligne cesse de correspondre à ce que la suite mesure pour elle.
<!-- noise-floor:start -->
| Requête parfaitement légitime | Ce qu'une installation non réglée journalise |
|---|---|
| `how to write a UNION SELECT in postgres` saisi dans un champ de recherche <!-- case: sql tutorial in a search box --> | `SQL Injection UNION` / high |
| Un article de blog contenant `<script>window.dataLayer=[];</script>` <!-- case: javascript snippet in a blog post --> | `XSS Script Tag` / high · `Command Chain Injection` / medium |
| Un ticket de support avec une erreur `SELECT * FROM users WHERE id = 1` collée <!-- case: a pasted sql error in a support ticket --> | `SQLi Variant` / high · `SQL SELECT Query` / low |
| Une documentation expliquant que `../../etc/passwd` est la charge utile classique de traversée de répertoire <!-- case: a traversal explainer in documentation --> | `Directory Traversal` / medium · `Sensitive File Access` / medium |
| Un formulaire de profil collectant un véritable numéro de mobile indien et un PAN <!-- case: a profile form collecting genuine indian pii --> | `PAN Number Detected` / high · `Bank Account Number Detected` / high · `Mobile Number Detected` / low |
<!-- noise-floor:end -->
**Aucun de ces cas n'est un bug.** Un article de blog contenant `<script>` est, octet
pour octet, une charge utile de XSS stocké ; une recherche de `UNION SELECT` est
indiscernable d'une tentative de ce type ; un numéro de mobile à dix chiffres est aussi un
numéro de compte bancaire plausible. Rien d'autre que le contexte applicatif ne les
distingue, et aucun moteur de motifs ne peut fournir ce contexte à votre place.
Le fournir est un changement de configuration d'une ligne : nommez le champ qui porte
légitimement ce type de contenu dans `safe_fields` (ou `safe_paths`, pour un chemin
précis dans du JSON imbriqué) et il n'est plus analysé. C'est l'interrupteur qui fait
taire les lignes ci-dessus — et c'est un vrai compromis, puisqu'une attaque délivrée via
ce champ passe aussi inaperçue.
`content_paths` et le mode `relaxed` sont des outils différents. Ils éliminent le bruit
de sévérité faible et moyenne, et **continuent délibérément d'enregistrer les
correspondances de sévérité élevée** — ils ne feront donc pas taire les lignes « high » de
ce tableau, par conception. Voir
[Reducing False Positives](#reducing-false-positives) pour savoir lequel utiliser selon
le cas.
**Si votre application accepte du texte enrichi, des exemples de code ou des requêtes de
recherche, faites-le avant de juger la sortie.** La valeur par défaut est délibérément
bruyante-mais-honnête plutôt que silencieuse-et-incomplète : il est plus facile de faire
taire une correspondance connue que de découvrir une correspondance qui ne s'est jamais
déclenchée.
### Alors, qu'en faites-vous concrètement ?
La question la plus fréquente à propos d'un détecteur qui ne bloque jamais. Quatre
réponses, par ordre croissant d'effort :
| Vous voulez | Utilisez | Effort |
|---|---|---|
| Voir ce qui vous frappe | Le [tableau de bord](#dashboard) ou `threat-detection:stats` | aucun, c'est déjà en marche |
| Bannir les récidivistes au pare-feu | [`threat-detection:export-fail2ban`](#artisan-commands) — pipe vers un cron | une ligne |
| Refuser au niveau du serveur web | [`threat-detection:export-blocklist`](#artisan-commands) → directives nginx/apache | une ligne |
| Refuser les requêtes dans l'application | [Helpers côté opérateur](#acting-on-the-data-operator-side-blocking) — `isBlocklisted()`, `isDdosThresholdExceeded()` | ~10 lignes de votre propre middleware |
| Réagir en temps réel | L'[événement `ThreatDetected`](#threatdetected-event) — Telegram, SIEM, PagerDuty | un listener |
Le package fournit le renseignement ; vous fournissez le refus. Cette séparation est
délibérée — le code d'application des règles qui vit dans votre application est du code
que vous pouvez lire, tester et désactiver, et cela signifie qu'un bug de détection ne
peut jamais mettre votre site hors service.
### Comment il se compare aux autres packages de sécurité Laravel
Ceux-ci résolvent des problèmes différents et se composent bien — le tableau sert à
choisir le bon outil, pas à désigner un gagnant.
| Package | Ce qu'il fait | Bloque ? | Utilisez-le quand |
|---|---|:---:|---|
| **ce package** | Analyse chaque requête selon 150+ motifs, journalise avec le contexte applicatif complet | ❌ | Vous voulez *voir* ce qui est tenté sur votre application |
| `spatie/laravel-honeypot` | Champ de formulaire caché qui attrape les bots de spam | ✅ formulaire uniquement | Vous avez des formulaires publics spammés |
| `graham-campbell/security` | Supprime le balisage de type XSS des entrées | ✅ modifie | Vous voulez une assainissement naïf des entrées |
| `spatie/laravel-csp` | Envoie des en-têtes Content-Security-Policy | ✅ navigateur | Vous voulez contraindre ce que le navigateur charge |
| `laravel/fortify` + limites de débit | Limitation et verrouillage de l'authentification | ✅ | Vous avez besoin d'une protection contre la force brute à la connexion |
| Cloudflare / mod_security | WAF edge, bloque avant votre application | ✅ | Vous voulez arrêter le trafic avant qu'il n'arrive |
Le résumé honnête : un honeypot attrape le spam de formulaire, un WAF bloque le trafic
connu comme malveillant à l'edge, et CSP contraint le navigateur. **Aucun d'entre eux ne
vous dit ce qu'un attaquant a tenté contre vos routes spécifiques, avec la charge utile
décodée et l'utilisateur authentifié attaché.** C'est ce vide que ce package comble — et
c'est pourquoi il ne bloque délibérément pas : vous pouvez l'exécuter aux côtés de tout ce
qui précède sans qu'aucun d'eux ne se combatte.
---
## Prérequis
- PHP 8.2+ (Laravel 13 nécessite PHP 8.3+)
- Laravel 10.x, 11.x, 12.x ou 13.x
- Toute base de données prise en charge par Laravel (MySQL, PostgreSQL, SQLite, SQL Server)
- N'importe quel driver de cache - **aucun Redis ni worker de file d'attente requis**. Redis/Memcached est
seulement *recommandé* pour activer la vérification DDoS optionnelle (qui se désactive automatiquement sur
les drivers non atomiques). Les écritures en file d'attente sont opt-in et désactivées par défaut.
---
## Comment ça marche
1. Un middleware analyse chaque requête HTTP entrante
2. La requête est vérifiée contre 158 motifs regex couvrant l'injection SQL, le XSS, le RCE, la traversée de fichiers, le SSRF, le LDAP, le XPath, le SSTI, et plus encore
3. Si un motif de menace correspond, un enregistrement est écrit dans votre table de base de données `threat_logs` avec l'IP, l'URL, le type de menace, le niveau de sévérité et un score de confiance
4. En option, une alerte Slack est envoyée pour les menaces de sévérité élevée
5. La requête se poursuit normalement - **rien n'est bloqué**
Aucune connexion internet n'est nécessaire pour la détection.
---
## Démarrage rapide
### 1. Installer le package
```bash
composer require jayanta/laravel-threat-detection
```
### 2. Publier les migrations et les exécuter
> **Cette étape est obligatoire.** Sans elle, le package détectera les menaces mais ne pourra pas les stocker dans la base de données. Si vous sautez cette étape, votre table `threat_logs` n'existera pas et toutes les détections seront silencieusement perdues (vous ne verrez les erreurs que dans `storage/logs/laravel.log`).
```bash
php artisan vendor:publish --tag=threat-detection-migrations
php artisan migrate
```
Cela crée deux tables : `threat_logs` (stocke les menaces détectées) et `threat_exclusion_rules` (stocke les règles de faux positifs).
**Vérifier que les tables ont été créées :**
```bash
php artisan migrate:status
```
Cherchez `create_threat_logs_table`, `add_confidence_to_threat_logs_table` et `create_threat_exclusion_rules_table` - tous devraient afficher `Ran`.
### 3. Enregistrer le middleware
Le middleware est ce qui analyse les requêtes. Vous devez l'ajouter à votre groupe de middleware `web`.
**Si vous utilisez Laravel 11 ou 12** - ouvrez `bootstrap/app.php` :
```php
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
\JayAnta\ThreatDetection\Http\Middleware\ThreatDetectionMiddleware::class,
]);
})
```
> **Comment vérifier votre version de Laravel :** exécutez `php artisan --version` dans votre terminal.
**Si vous utilisez Laravel 10** - ouvrez `app/Http/Kernel.php` :
```php
protected $middlewareGroups = [
'web' => [
// ... existing middleware
\JayAnta\ThreatDetection\Http\Middleware\ThreatDetectionMiddleware::class,
],
];
```
### 4. (Facultatif) Publier le fichier de configuration
```bash
php artisan vendor:publish --tag=threat-detection-config
```
Le package fonctionne avec des valeurs par défaut sensées. Publier la configuration vous permet de personnaliser les motifs de détection, les modes de sensibilité, les notifications Slack, et plus encore. Si vous sautez cette étape, tout fonctionne quand même.
**C'est tout.** Votre application détecte désormais les menaces.
---
## Vérifier que cela fonctionne
Après l'installation, déclenchez une menace de test et confirmez qu'elle a été enregistrée.
### Étape 1 : Démarrer votre application
```bash
php artisan serve
```
### Étape 2 : Ouvrez une URL de test dans votre navigateur
Ajoutez un paramètre de requête malveillant à **n'importe quelle route existante** de votre application (votre page d'accueil, une page produit, etc.). Par exemple :
**Injection SQL :**
```
http://localhost:8000/?q=' UNION SELECT * FROM users--
```
**XSS (Cross-Site Scripting) :**
```
http://localhost:8000/?q=<script>alert(1)</script>
```
**Traversée de répertoire :**
```
http://localhost:8000/?file=../../etc/passwd
```
**RCE (exécution de code à distance) :**
```
http://localhost:8000/?cmd=system('ls -la')
```
**Shellshock (CVE-2014-6271) :**
```
http://localhost:8000/?cmd=() { :;}; /bin/bash
```
**Injection de commandes Windows :**
```
http://localhost:8000/?cmd=powershell -c whoami
```
**DROP TABLE (SQL DDL) :**
```
http://localhost:8000/?q=DROP TABLE users
```
> Utilisez une route qui existe réellement dans votre application (comme `/`). Si l'URL renvoie un 404, le middleware n'a peut-être pas été exécuté.
### Étape 3 : Vérifier que les menaces ont été enregistrées
**Option A - Commande Artisan (la plus rapide) :**
```bash
php artisan threat-detection:stats
```
Vous devriez voir un tableau avec `Recorded Detections`, les décomptes de sévérité et les principales IP. Ce nombre compte des *lignes*, pas des tentatives : une détection est écrite une fois par IP par type de menace par tranche de cinq minutes, et les répétitions à l'intérieur de cette fenêtre sont dédupliquées plutôt que comptées à nouveau.
**Option B - Tinker :**
```bash
php artisan tinker
```
```php
DB::table('threat_logs')->latest()->take(5)->get(['ip_address', 'type', 'threat_level', 'confidence_score']);
```
**Option C - Fichier de log Laravel :**
Chaque menace détectée est écrite sous forme d'avertissement dans `storage/logs/laravel.log` :
```
[high] Threat Detected: [middleware] SQL Injection UNION from 127.0.0.1 (http://localhost:8000/?q=...) [confidence: 50%]
```
### Points à connaître lors des tests
| Comportement | Explication |
|----------|-------------|
| Une même menace n'est journalisée qu'une fois toutes les 5 minutes | Déduplication : la même IP + le même type de menace est mis en cache pendant 5 minutes. Utilisez **différents types d'attaques** pour chaque test, ou attendez entre les tests. |
| Les requêtes `curl` déclenchent une détection supplémentaire | L'utilisation de `curl` journalise également une détection de user-agent « cURL Command » (sévérité faible). C'est attendu - le package détecte les outils automatisés. |
| Le package ne bloque jamais les requêtes | Votre application continue de fonctionner normalement. La détection est passive. |
| Aucune configuration Slack nécessaire | Les notifications sont désactivées par défaut. |
| Aucune connexion internet nécessaire | La détection principale est 100 % locale. Seule la commande optionnelle `threat-detection:enrich` appelle une API externe pour les géo-données. |
### Dépannage
**Commencez ici — une seule commande répond à la plupart de ces points :**
```bash
php artisan threat-detection:doctor
```
Il vérifie les éléments qui font échouer la détection *silencieusement* — là où le tableau de bord reste vide, ce qui ressemble à « aucune attaque » — et affiche la correction exacte pour chacun. Il se termine avec un code non nul en cas d'échec réel, il est donc sûr de l'exécuter dans une CI ou une étape de déploiement.
```
Threat Detection — health check
PASS Detection is enabled for this environment
FAIL 'threat_logs' is missing confidence_label — EVERY threat is being discarded
Run: php artisan vendor:publish --tag=threat-detection-migrations && php artisan migrate
WARN 1 custom pattern(s) shadow a built-in: Localhost SSRF
Your copy runs instead of the maintained one, so later fixes to it never reach you.
```
Ce qu'il couvre : la détection activée pour cet environnement ; chaque colonne dont le writer
a besoin (une colonne manquante élimine **toutes** les menaces) ; les colonnes du dashboard/API ; la
table des règles d'exclusion ; si le middleware est réellement connecté à une route ou à un
groupe ; une configuration publiée antérieure à cette version ; des motifs personnalisés qui masquent
ceux intégrés ; un driver de cache incapable de faire du comptage DDoS ; et un dashboard ou une
API laissé ouvert sans authentification.
**« J'ai testé mais `threat-detection:stats` affiche zéro menace » / « Les menaces ne sont pas stockées dans la base de données »**
Si le doctor est passé, l'installation est correcte et le problème vient de la requête de test
elle-même. Trois choses qu'il ne peut pas vérifier à votre place :
| Vérification | Comment vérifier |
|-------|---------------|
| L'IP n'est pas en liste blanche | Si vous avez ajouté `THREAT_DETECTION_WHITELISTED_IPS` au `.env`, retirez-le pendant les tests |
| Utilisation d'une route existante | L'URL de test doit correspondre à une route réelle (par ex., `/`). Un 404 signifie que le middleware ne s'est jamais exécuté |
| Cache de déduplication | Même IP + même type d'attaque est mis en cache pendant 5 minutes - essayez un autre type d'attaque |
> Exécuter `php artisan migrate` seul ne suffit jamais : les fichiers de migration se trouvent
> à l'intérieur du package et doivent d'abord être publiés dans le `database/migrations/`
> de votre application. Le doctor affiche la commande exacte lorsque c'est le problème.
**« L'API renvoie 401 Unauthorized »**
Voir [Authentification de l'API](#api-authentication) ci-dessous.
**« Le dashboard affiche 404 »**
Le dashboard est désactivé par défaut. Ajoutez `THREAT_DETECTION_DASHBOARD=true` au `.env` et videz le cache des routes :
```bash
php artisan route:clear
```
---
## Fonctionnalités
- **Plus de 150 motifs de détection** - Injection SQL (UNION, DDL, DML, opérations sur fichiers), XSS (script, SVG, expression CSS), RCE, traversée de répertoire, SSRF, XXE, Log4Shell, injection NoSQL, injection de commandes (Linux + Windows), injection LDAP, injection XPath, SSTI, injection CRLF, désérialisation Java, et plus encore
- **83 signatures de bots/scanners** - SQLMap, Nikto, Nmap, Burp Suite, FeroxBuster, FFUF, XSStrike, Dalfox, Netsparker, et plus de 70 autres signatures de scanners et bots
- **Détection des scrapers IA** - GPTBot, ClaudeBot, ByteSpider, Common Crawl, et autres bots d'entraînement IA
- **Détection des navigateurs headless** - HeadlessChrome, PhantomJS, Selenium, Puppeteer, Playwright
- **Suivi des sondes 404** - Détecte les sondes de reconnaissance ciblant des chemins vulnérables connus (`/wp-admin`, `/.env`, `/phpmyadmin`, `/actuator`, etc.) avec plus de 50 chemins de sonde par défaut, plus un [pack d'infrastructure IA](#ai-infrastructure-probes-opt-in) optionnel pour les passerelles LLM exposées
- **Surveillance DDoS** - Détection par seuil de débit avec fenêtres configurables
- **Score de confiance** - Chaque menace reçoit un score de confiance de 0 à 100 basé sur le nombre de motifs, le contexte et les signaux
- **Résistance à l'évasion** - Le pipeline de normalisation neutralise l'insertion de commentaires SQL, le double encodage URL, l'encodage d'entités HTML, les échappements Unicode, les échappements hexadécimaux et l'encodage IIS `%uXXXX` avant la correspondance des motifs — répété jusqu'à ce que la charge utile cesse de changer, de sorte que l'empilement de deux techniques ne permet pas de passer outre
- **Détection de CVE** - Shellshock (CVE-2014-6271), Spring4Shell (CVE-2022-22965), PHPUnit RCE (CVE-2017-9841), Drupalgeddon, Log4Shell
- **Détection contextuelle** - Les motifs trouvés dans les chaînes de requête obtiennent un score plus élevé que ceux trouvés dans le corps de la requête
- **Analyse du corps de requête** - Les corps de requête encodés en formulaire et JSON (`application/json`) sont inspectés
- **Champs sûrs** - Exclure des champs de formulaire spécifiques de l'analyse (pour les éditeurs CMS, les entrées de code, les champs de recherche)
- **Signalement de faux positifs** - Marquer les menaces comme faux positifs depuis le tableau de bord ; crée automatiquement des règles d'exclusion
- **Trois modes de détection** - `strict`, `balanced` (par défaut) et `relaxed` - sensibilité ajustable
- **Suppression des chemins de contenu** - Mettre en liste blanche les chemins CMS/blog pour supprimer les alertes de niveau faible/moyen provenant de contenu riche
- **Détection de PII** - Motifs d'exposition de données sensibles (configurable par région)
- **Géo-enrichissement** - Identification du pays, de la ville, du FAI, du fournisseur cloud via une API gratuite
- **Alertes Slack** - Notifications en temps réel pour les menaces de haute gravité (fonctionne sur Laravel 10 et 11+)
- **Tableau de bord intégré** - Tableau de bord Blade en mode sombre (Alpine.js et Tailwind, styles précompilés, aucune étape de build)
- **Garde d'authentification du tableau de bord** - Authentification configurable pour le tableau de bord et l'API (aucune, auth, rôle ou basée sur l'IP)
- **15 points de terminaison API** - API REST complète pour créer des tableaux de bord personnalisés Vue/React/mobile
- **Export Fail2ban** - Exporter les IP détectées dans un format compatible fail2ban ou une liste de blocage simple
- **Export de liste de blocage** - Exporter les IP au format nginx deny, Apache deny, CSV ou simple
- **Export CSV** - Export du journal des menaces en un clic (jusqu'à 10 000 lignes)
- **Analyse de corrélation** - Détecter les attaques coordonnées et les campagnes d'attaque entre les IP
- **Optimisation des performances** - Chargement paresseux des motifs par catégorie (n'exécute les regex que pour les catégories d'attaque pertinentes), sortie anticipée pour les requêtes propres, court-circuit sur l'UA du navigateur (ignore plus de 70 vérifications pour les navigateurs normaux), recherche par hachage des chemins de sonde, insertions DB par lots, nombre maximal de détections configurable par requête
- **Indépendant de la base de données** - MySQL, PostgreSQL, SQLite, SQL Server
- **Zéro configuration** - Fonctionne immédiatement avec des valeurs par défaut sensées
- **Sûr par conception** - Le middleware intercepte ses propres erreurs. Si la détection échoue, votre application continue de fonctionner. Les requêtes ne sont jamais bloquées.
---
## Configuration
Le package fonctionne sans aucune modification du fichier `.env`. Toutes les valeurs ci-dessous sont optionnelles - ajoutez-les uniquement si vous souhaitez remplacer les valeurs par défaut.
```env
# Enable/disable detection globally (default: true)
THREAT_DETECTION_ENABLED=true
# Detection sensitivity (default: balanced)
# Options: strict, balanced, relaxed
THREAT_DETECTION_MODE=balanced
# Custom table name (default: threat_logs)
# THREAT_DETECTION_TABLE=threat_logs
# Your ISO 3166-1 alpha-2 country code (default: IN)
# Drives the is_foreign flag on every enriched row — set this or every
# non-Indian address is reported as foreign.
# THREAT_DETECTION_HOME_COUNTRY=IN
# Geo-enrichment provider used by threat-detection:enrich (default shown).
# HTTPS since v1.8.0. A failed lookup is never retried over cleartext, and a
# run in which every lookup failed exits non-zero rather than reporting
# success. Enrichment is opt-in either way.
#
# ip-api.com's free tier rejects HTTPS, so on the free tier this command will
# now fail rather than quietly sending your visitors' IP addresses in the
# clear. Either point it at a provider you hold a key for, or set it back
# explicitly and accept the disclosure.
# THREAT_DETECTION_GEO_ENDPOINT=https://ip-api.com/json
# Dashboard URL path (default: threat-detection)
# THREAT_DETECTION_DASHBOARD_PATH=threat-detection
# API route prefix (default: api/threat-detection)
# THREAT_DETECTION_API_PREFIX=api/threat-detection
# Role required when the API guard is 'role' (default: admin)
# THREAT_DETECTION_API_ROLE=admin
# Allowed IPs when the API guard is 'ip'. Comma-separated, CIDR supported.
# THREAT_DETECTION_API_IPS=127.0.0.1,10.0.0.0/8
# Username shown on Slack alerts (default: ThreatBot)
# THREAT_DETECTION_SLACK_USERNAME=ThreatBot
# Whitelist IPs to skip detection entirely (default: empty)
# Supports CIDR notation. Comma-separated.
# THREAT_DETECTION_WHITELISTED_IPS=10.0.0.0/8,192.168.1.0/24
# Static operator denylist read by ThreatDetection::isBlocklisted() (default: empty)
# The package itself never blocks — see "Acting on the Data" for the
# enforcement recipe. Supports CIDR. Whitelist wins on overlap.
# THREAT_DETECTION_BLOCKLISTED_IPS=203.0.113.0/24,198.51.100.7
# DDoS detection thresholds (defaults shown)
# THREAT_DETECTION_DDOS_THRESHOLD=300
# THREAT_DETECTION_DDOS_WINDOW=60
# Minimum confidence score to log a threat (default: 0)
# Threats below this score are silently ignored.
# THREAT_DETECTION_MIN_CONFIDENCE=0
# Slack notifications (disabled by default)
# THREAT_DETECTION_NOTIFICATIONS=true
# THREAT_DETECTION_SLACK_WEBHOOK=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
# THREAT_DETECTION_SLACK_CHANNEL=#threat-alerts
# Dashboard (disabled by default)
# THREAT_DETECTION_DASHBOARD=true
# API endpoints (enabled by default)
# THREAT_DETECTION_API=true
# API rate limiting (default: 60 requests per minute)
# THREAT_DETECTION_API_THROTTLE=60,1
# Queue support - offload DB writes to a queue (disabled by default).
# OPTIONAL: only enable if your app already runs a queue worker. When false
# (default), threats are written synchronously with a plain DB insert - no
# Redis, no worker, nothing extra to run.
# THREAT_DETECTION_QUEUE=false
# THREAT_DETECTION_QUEUE_CONNECTION=redis
# THREAT_DETECTION_QUEUE_NAME=default
# Auto-purge old logs (disabled by default)
# Requires Laravel scheduler to be running.
# THREAT_DETECTION_RETENTION=false
# THREAT_DETECTION_RETENTION_DAYS=90
# 404 probe tracking (enabled by default)
# Detects bots hitting /wp-admin, /.env, /phpmyadmin, etc.
# THREAT_DETECTION_PROBE_TRACKING=true
# Max detections per request (default: 0 = unlimited)
# Stop scanning after N pattern matches per request.
# THREAT_DETECTION_MAX_DETECTIONS=0
```
---
[Read more](https://github.com/jay123anta/laravel-threat-detection)