
Middleware Laravel passivo che rileva e registra SQL injection, XSS, RCE, scanner bot e oltre 175 pattern di attacco. Include una dashboard integrata, avvisi Slack, API REST e arricchimento geografico. IDS, non WAF.
Monitoraggio della sicurezza e registrazione degli attacchi per Laravel. Rileva e registra SQL injection,
XSS, RCE, directory traversal, scanner bot e sonde di ricognizione in stile /wp-admin —
ogni richiesta ostile viene registrata nel tuo database con il pieno contesto dell'applicazione.
È un IDS, non un WAF: non blocca, filtra o modifica mai una richiesta.
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
Queste richieste stanno già raggiungendo la tua app Laravel. Il tuo log di accesso mostra l'URL
e il codice di stato, e nient'altro — non il payload decodificato, non quale delle tue
route è stata presa di mira, non se lo stesso IP ha provato altre quaranta cose in quest'ora.
Questo pacchetto risponde a queste domande. Installalo in qualsiasi app Laravel 10–13 e inizierà
a scansionare ogni richiesta HTTP contro oltre 150 pattern di attacco, assegnando un punteggio a ogni corrispondenza in base alla
confidenza e scrivendolo nel tuo database — con una dashboard integrata, avvisi Slack,
geo-arricchimento ed esportazioni fail2ban/blocklist. Nessuna richiesta viene mai bloccata. Pensalo come una
telecamera di sicurezza, non un lucchetto: ti mostra esattamente chi sta sondando le tue route, con quale
frequenza e con quali tecniche.
> Estratto da un'app in produzione e testato sul traffico reale. 335 test, nessuna dipendenza a runtime
> oltre a Laravel stesso, e nessuna connessione internet richiesta per il rilevamento.
>
> Stai facendo un aggiornamento? Vedi [UPGRADING.md](https://github.com/jay123anta/laravel-threat-detection/blob/main/UPGRADING.md). Vuoi contribuire? Vedi [CONTRIBUTING.md](https://github.com/jay123anta/laravel-threat-detection/blob/main/CONTRIBUTING.md).
## Inizia in meno di un minuto```bash
composer require jayanta/laravel-threat-detection
php artisan vendor:publish --tag=threat-detection-migrations
php artisan migrate
Poi aggiungi il middleware al tuo gruppo web (una riga in bootstrap/app.php su Laravel 11+,
o app/Http/Kernel.php su Laravel 10) — snippet completo in Quick Start qui sotto.
Tutto qui; il rilevamento è attivo.```bash
php artisan threat-detection:doctor # confirms it is actually recording
---
## Dove si colloca: IDS vs WAF vs edge
Questo pacchetto è un **IDS passivo a livello di applicazione** — osserva e registra, non
blocca. È pensato per stare *accanto* a un WAF o a un servizio edge, non per sostituirlo. Ogni livello vede
qualcosa che gli altri non vedono:
| | **Questo pacchetto** (IDS app) | **WAF** (mod_security, Cloudflare WAF) | **Edge / CDN** (Cloudflare) |
|---|:---:|:---:|:---:|
| Blocca le richieste dannose | ❌ solo log | ✅ | ✅ |
| Contesto completo dell'app (rotta esatta, payload decodificato, utente autenticato) | ✅ | ⚠️ parziale | ❌ |
| Dashboard integrata + log delle minacce nel tuo DB | ✅ | ⚠️ varia | ⚠️ solo edge |
| Rilevamenti specifici dell'app (es. PII Aadhaar / PAN / IFSC) | ✅ pattern personalizzati | ❌ | ❌ |
| Funziona offline / nessun servizio esterno | ✅ | ⚠️ dipende | ❌ |
| Ferma il traffico prima che raggiunga la tua app | ❌ | ✅ edge | ✅ |
| Configurazione | un `composer require` | medio–alto | basso–medio |
| Costo | gratuito, MIT | varia | livello gratuito + a pagamento |
**In breve:** un edge/WAF è la serratura sulla porta; questo è la telecamera di sicurezza
*all'interno*, con il contesto dell'app per dirti esattamente cosa viene tentato su quale rotta, da
chi, e con quale frequenza. Usalo per alimentare decisioni reali — ban fail2ban, limiti di
rate, geo-blocking — con dati che il tuo livello edge non vede mai.
### Cosa deliberatamente NON è
- **Non è un WAF.** Non blocca, filtra o modifica mai una richiesta. Usa Cloudflare,
mod_security o un vero WAF per l'applicazione delle regole. (Nessun livello edge a cui delegare? Gli
[helper lato operatore](#acting-on-the-data-operator-side-blocking) espongono le
decisioni del pacchetto così puoi scrivere il tuo middleware di blocco di cinque righe —
il codice di enforcement resta tuo, non del pacchetto.)
- **Non sostituisce la programmazione sicura.** Query parametrizzate, validazione degli input ed
escaping dell'output sono le tue vere difese. Questo pacchetto presuppone che il tuo codice sia già
sicuro e ti offre *visibilità*, non protezione.
- **Non è un servizio edge.** Se puoi mettere Cloudflare davanti, fallo — poi aggiungi questo per il
dettaglio a livello di applicazione che i servizi edge non possono vedere.
### Quindi cosa ci fai concretamente?
La domanda più comune su un rilevatore che non blocca mai. Quattro risposte, in
ordine crescente di impegno:
| Vuoi | Usa | Impegno |
|---|---|---|
| Vedere cosa ti sta colpendo | La [dashboard](#dashboard) o `threat-detection:stats` | nessuno, è già in esecuzione |
| Bannare i recidivi al firewall | [`threat-detection:export-fail2ban`](#artisan-commands) — convoglia in un cron | una riga |
| Negare al web server | [`threat-detection:export-blocklist`](#artisan-commands) → direttive nginx/apache | una riga |
| Rifiutare le richieste nell'app | [Helper lato operatore](#acting-on-the-data-operator-side-blocking) — `isBlocklisted()`, `isDdosThresholdExceeded()` | ~10 righe di middleware tuo |
| Reagire in tempo reale | L'[evento `ThreatDetected`](#threatdetected-event) — Telegram, SIEM, PagerDuty | un listener |
Il pacchetto fornisce l'intelligenza; tu fornisci il rifiuto. Questa separazione è
deliberata — il codice di enforcement che vive nella tua app è codice che puoi leggere,
testare e disattivare, e significa che un bug di rilevamento non può mai mandare giù il tuo sito.
### Come si confronta con altri pacchetti di sicurezza Laravel
Questi risolvono problemi diversi e si compongono bene — la tabella serve a scegliere lo
strumento giusto, non a vincere.
| Pacchetto | Cosa fa | Blocca? | Usalo quando |
|---|---|:---:|---|
| **questo pacchetto** | Scansiona ogni richiesta contro 150+ pattern, registra con contesto completo dell'app | ❌ | Vuoi *vedere* cosa viene tentato sulla tua app |
| `spatie/laravel-honeypot` | Campo modulo nascosto che cattura i bot spam | ✅ solo modulo | Hai moduli pubblici che ricevono spam |
| `graham-campbell/security` | Rimuove markup simile a XSS dall'input | ✅ muta | Vuoi una sanificazione ingenua dell'input |
| `spatie/laravel-csp` | Invia header Content-Security-Policy | ✅ browser | Vuoi limitare ciò che il browser carica |
| `laravel/fortify` + limiti di rate | Throttling e blocco dell'autenticazione | ✅ | Ti serve protezione da forza bruta sul login |
| Cloudflare / mod_security | WAF edge, blocca prima della tua app | ✅ | Vuoi che il traffico venga fermato prima che arrivi |
Il riepilogo onesto: un honeypot cattura lo spam dei moduli, un WAF blocca il traffico noto-dannoso
all'edge, e CSP limita il browser. **Nessuno di questi ti dice cosa un
attaccante ha tentato contro le tue rotte specifiche, con il payload decodificato e
l'utente autenticato allegato.** È quel vuoto che questo colma — ed è il motivo per cui il
pacchetto deliberatamente non blocca: puoi eseguirlo insieme a tutti quelli sopra
senza che nessuno entri in conflitto con gli altri.
---
## Requisiti
- PHP 8.2+ (Laravel 13 richiede PHP 8.3+)
- Laravel 10.x, 11.x, 12.x o 13.x
- Qualsiasi database supportato da Laravel (MySQL, PostgreSQL, SQLite, SQL Server)
- Qualsiasi driver di cache — **nessun Redis o worker di coda richiesto**. Redis/Memcached è
solo *consigliato* per abilitare il controllo DDoS opzionale (che si disattiva automaticamente sui
driver non atomici). Le scritture in coda sono opt-in e disattivate di default.
---
## Come Funziona
1. Un middleware scansiona ogni richiesta HTTP in arrivo
2. La richiesta viene controllata contro 158 pattern regex che coprono SQL injection, XSS, RCE, file traversal, SSRF, LDAP, XPath, SSTI e altro
3. Se un pattern di minaccia corrisponde, viene scritto un record nella tua tabella database `threat_logs` con IP, URL, tipo di minaccia, livello di gravità e un punteggio di confidenza
4. Facoltativamente, viene inviato un avviso Slack per le minacce ad alta gravità
5. La richiesta procede normalmente — **nulla viene bloccato**
Non è necessaria alcuna connessione internet per il rilevamento.
---
## Avvio Rapido
### 1. Installa il pacchetto```bash
composer require jayanta/laravel-threat-detection
Questo passaggio è obbligatorio. Senza di esso, il pacchetto rileverà le minacce ma non potrà memorizzarle nel database. Se salti questo passaggio, la tua tabella
threat_logsnon esisterà e tutte le rilevazioni andranno perse silenziosamente (vedrai solo errori instorage/logs/laravel.log).```bash php artisan vendor:publish --tag=threat-detection-migrations php artisan migrate
Questo crea due tabelle: `threat_logs` (memorizza le minacce rilevate) e `threat_exclusion_rules` (memorizza le regole per i falsi positivi).
**Verifica che le tabelle siano state create:**```bash
php artisan migrate:status
Look for create_threat_logs_table, add_confidence_to_threat_logs_table, e create_threat_exclusion_rules_table - tutti dovrebbero mostrare Ran.
Il middleware è ciò che analizza le richieste. Devi aggiungerlo al tuo gruppo di middleware web.
Se usi Laravel 11 o 12 - apri bootstrap/app.php:```php
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
\JayAnta\ThreatDetection\Http\Middleware\ThreatDetectionMiddleware::class,
]);
})
> **Come controllare la tua versione di Laravel:** Esegui `php artisan --version` nel tuo terminale.
**Se usi Laravel 10** - apri `app/Http/Kernel.php`:```php
protected $middlewareGroups = [
'web' => [
// ... existing middleware
\JayAnta\ThreatDetection\Http\Middleware\ThreatDetectionMiddleware::class,
],
];
php artisan vendor:publish --tag=threat-detection-config
Il pacchetto funziona con impostazioni predefinite sensate. Pubblicare la configurazione ti consente di personalizzare i pattern di rilevamento, le modalità di sensibilità, le notifiche Slack e altro. Se salti questo passaggio, tutto funziona comunque.
**Questo è tutto.** La tua app ora sta rilevando le minacce.
---
## Verifica che funzioni
Dopo l'installazione, attiva una minaccia di test e conferma che sia stata registrata.
### Passaggio 1: Avvia la tua app```bash
php artisan serve
Aggiungi un parametro di query dannoso a qualsiasi route esistente nella tua app (la tua homepage, una pagina prodotto, ecc.). Ad esempio:
SQL Injection:``` http://localhost:8000/?q=' UNION SELECT * FROM users--
**XSS (Cross-Site Scripting):**```
http://localhost:8000/?q=<script>alert(1)</script>
Directory Traversal:``` http://localhost:8000/?file=../../etc/passwd
**RCE (Remote Code Execution):**```
http://localhost:8000/?cmd=system('ls -la')
Shellshock (CVE-2014-6271):``` http://localhost:8000/?cmd=() { :;}; /bin/bash
**Windows Command Injection:**```
http://localhost:8000/?cmd=powershell -c whoami
DROP TABLE (SQL DDL):``` http://localhost:8000/?q=DROP TABLE users
> Usa una rotta che esista effettivamente nella tua app (come `/`). Se l'URL restituisce un 404, il middleware potrebbe non essere stato eseguito.
### Passaggio 3: Verifica che le minacce siano state registrate
**Opzione A - Comando Artisan (il più rapido):**```bash
php artisan threat-detection:stats
Opzione B - Tinker:```bash php artisan tinker
```php
DB::table('threat_logs')->latest()->take(5)->get(['ip_address', 'type', 'threat_level', 'confidence_score']);
Opzione C - File di log Laravel:
Ogni minaccia rilevata viene scritta come avviso in storage/logs/laravel.log:```
[high] Threat Detected: [middleware] SQL Injection UNION from 127.0.0.1 (http://localhost:8000/?q=...) [confidence: 50%]
### Cose da sapere durante i test
| Comportamento | Spiegazione |
|----------|-------------|
| La stessa minaccia viene registrata solo una volta ogni 5 minuti | Deduplicazione: stesso IP + stesso tipo di minaccia viene memorizzato nella cache per 5 minuti. Usa **tipi di attacco diversi** per ogni test, oppure attendi tra un test e l'altro. |
| Le richieste `curl` attivano un rilevamento aggiuntivo | Usare `curl` registra anche un rilevamento dello user-agent "cURL Command" (severità bassa). È previsto: il pacchetto rileva gli strumenti automatizzati. |
| Il pacchetto non blocca mai le richieste | La tua app continua a funzionare normalmente. Il rilevamento è passivo. |
| Nessuna configurazione di Slack necessaria | Le notifiche sono disattivate per impostazione predefinita. |
| Nessuna connessione internet necessaria | Il rilevamento principale è 100% locale. Solo il comando opzionale `threat-detection:enrich` chiama un'API esterna per i dati geografici. |
### Risoluzione dei problemi
**Inizia da qui: un solo comando risponde alla maggior parte delle domande:**```bash
php artisan threat-detection:doctor
Controlla gli elementi che fanno fallire il rilevamento in silenzio — dove la dashboard rimane vuota, il che appare identico a "nessun attacco" — e stampa la correzione esatta per ciascuno. Esce con codice non zero in caso di errore reale, quindi è sicuro eseguirlo in CI o in una fase di deploy.``` 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.
Cosa copre: rilevamento abilitato per questo ambiente; ogni colonna di cui lo
scrittore ha bisogno (una mancante scarta **ogni** minaccia); colonne della dashboard/API; la
tabella delle regole di esclusione; se il middleware è effettivamente collegato a una rotta o
gruppo; config pubblicata che precede questa versione; pattern personalizzati che oscurano
quelli integrati; un driver di cache che non può fare il conteggio DDoS; e una dashboard o
API lasciata aperta senza autenticazione.
**"Ho testato ma `threat-detection:stats` mostra zero minacce" / "Le minacce non vengono salvate nel database"**
Se il doctor è passato, l'installazione è corretta e il problema è la richiesta di test
stessa. Tre cose che non può verificare per te:
| Controllo | Come verificare |
|-------|---------------|
| L'IP non è in whitelist | Se hai aggiunto `THREAT_DETECTION_WHITELISTED_IPS` a `.env`, rimuovilo durante il test |
| Usata una rotta esistente | L'URL di test deve corrispondere a una rotta reale (es. `/`). Un 404 significa che il middleware non è mai stato eseguito |
| Cache di deduplicazione | Stesso IP + stesso tipo di attacco viene memorizzato in cache per 5 minuti - prova un tipo di attacco diverso |
> Eseguire `php artisan migrate` da solo non è mai sufficiente: i file di migrazione si trovano
> all'interno del pacchetto e devono essere pubblicati nella cartella `database/migrations/` della
> tua app prima. Il doctor stampa il comando esatto quando questo è il problema.
**"L'API restituisce 401 Unauthorized"**
Vedi [Autenticazione API](#api-authentication) di seguito.
**"La dashboard mostra 404"**
La dashboard è disabilitata per impostazione predefinita. Aggiungi `THREAT_DETECTION_DASHBOARD=true` a `.env` e svuota la cache delle rotte:```bash
php artisan route:clear
/wp-admin, /.env, /phpmyadmin, /actuator, ecc.) con oltre 50 percorsi di sonda predefinitiapplication/json)strict, balanced (predefinita) e relaxed - sensibilità regolabileIl pacchetto funziona senza alcuna modifica al file .env. Tutti i valori seguenti sono opzionali - aggiungili solo se vuoi sovrascrivere le impostazioni predefinite.```env
THREAT_DETECTION_ENABLED=true
THREAT_DETECTION_MODE=balanced
### Modalità di Rilevamento
| Modalità | Soglia di Confidenza | Comportamento |
|----------|----------------------|---------------|
| `strict` | 0 (registra tutto) | Tutti i pattern attivi, soglie più basse. Rileva tutto ma potrebbe segnalare traffico legittimo. |
| `balanced` | 10 | Predefinita. Scoring di confidenza attivo, soglie standard. Adatta per la maggior parte delle app. |
| `relaxed` | 40 | Solo i pattern ad alta severità attivano. Ideale per siti ricchi di contenuti con frequenti falsi positivi. |
### Ambienti Abilitati
Per impostazione predefinita, il rilevamento viene eseguito in `production`, `staging` e `local`. Per modificarlo, pubblica la configurazione e modifica:```php
'enabled_environments' => ['production', 'staging', 'local'],
Per disabilitare il rilevamento nella tua suite di test, imposta APP_ENV=testing (non nell'elenco sopra) o aggiungi al tuo phpunit.xml:```xml
### Riferimento alla Configurazione
Pubblica il file di configurazione per vedere tutte le opzioni disponibili:```bash
php artisan vendor:publish --tag=threat-detection-config
Sezioni di configurazione chiave: skip_paths (percorsi da saltare), only_paths (modalità whitelist), auth_paths (rilevamento intelligente per le rotte di login), content_paths (soppressione degli alert non critici), safe_fields (esclusione di campi specifici dalla scansione), safe_paths (esclusione di campi sensibile al percorso per JSON annidati), probe_tracking (rilevamento probe 404), context_weights (moltiplicatori di punteggio), threat_levels (mappatura delle parole chiave di gravità), api_route_filtering (soppressione di alert bassi/medi sulle rotte API), queue (elaborazione asincrona), retention (pulizia automatica), max_detections_per_request (limite di prestazioni), dashboard.guard / api.guard (modalità di autenticazione).
only_paths)Se la tua app ha molte rotte ma ti interessano solo alcune, usa only_paths per scansionare solo quelle rotte. Tutte le altre rotte vengono saltate automaticamente - nessun overhead del middleware.```php
// config/threat-detection.php
'only_paths' => [
'admin/',
'api/',
'login',
'register',
],
Lascia vuoto (predefinito) per scansionare tutte le route (soggetto a `skip_paths`). Quando entrambi sono configurati, `only_paths` viene controllato per primo, poi `skip_paths` si applica all'interno del set corrispondente.
### Supporto Code
Per impostazione predefinita, la registrazione delle minacce avviene in modo sincrono nel ciclo di richiesta. Per applicazioni ad alto traffico, puoi scaricare le scritture sul database e le notifiche Slack su una coda:```env
THREAT_DETECTION_QUEUE=true
THREAT_DETECTION_QUEUE_CONNECTION=redis
THREAT_DETECTION_QUEUE_NAME=threat-logs
Questo invia un job StoreThreatLog (3 tentativi, backoff 10s/30s). Il rilevamento avviene comunque in tempo reale - solo la scrittura viene posticipata.
Elimina automaticamente i vecchi log delle minacce con una pianificazione giornaliera:```env THREAT_DETECTION_RETENTION=true THREAT_DETECTION_RETENTION_DAYS=90
Richiede che lo scheduler di Laravel sia in esecuzione (`php artisan schedule:run`). Viene eseguito ogni giorno alle 02:00 tramite `threat-detection:purge`.
### Evento ThreatDetected
Ogni minaccia confermata genera un evento `ThreatDetected` a cui puoi fare da listener:```php
// app/Providers/EventServiceProvider.php
use JayAnta\ThreatDetection\Events\ThreatDetected;
protected $listen = [
ThreatDetected::class => [
YourCustomListener::class,
],
];
L'evento trasporta $threatLog (array completo della riga del DB), $ipAddress e $threatLevel. Usalo per attivare azioni personalizzate: inviare avvisi Telegram, aggiornare una blocklist, alimentare un SIEM, ecc.
Quando un client supera la soglia DDoS configurata (ddos.threshold richieste entro
ddos.window secondi), viene generato un evento DdosThresholdExceeded insieme alla
voce del log delle minacce:```php
use JayAnta\ThreatDetection\Events\DdosThresholdExceeded;
protected $listen = [ DdosThresholdExceeded::class => [ YourFloodListener::class, ], ];
The event carries `$ipAddress`, `$requestCount`, `$threshold`, and `$windowSeconds`. It is
throttled to once per IP per dedup window (same throttle as the log row), so a flood can't
drown your listeners. Use it for alerting or to feed an external ban store; to *refuse*
over-threshold clients, use `ThreatDetection::isDdosThresholdExceeded($ip)` from your own
middleware instead — see [Acting on the Data](#acting-on-the-data-operator-side-blocking).
---
## Slack Notifications
Slack alerts are disabled by default. To enable:```env
THREAT_DETECTION_NOTIFICATIONS=true
THREAT_DETECTION_SLACK_WEBHOOK=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
THREAT_DETECTION_SLACK_CHANNEL=#threat-alerts
Solo le minacce ad alta gravità attivano le notifiche per impostazione predefinita (configurabile tramite notify_levels nel config).
Laravel 10: Utilizza la classe di notifica integrata SlackMessage. Non è necessario alcun pacchetto aggiuntivo.
Laravel 11+: Il canale Slack integrato è stato rimosso. Il pacchetto rileva automaticamente questa situazione e invia webhook HTTP POST grezzi al tuo URL Slack. Non è necessario alcun pacchetto aggiuntivo. Se preferisci il canale di notifica completo, installa:```bash composer require laravel/slack-notification-channel
---
## Dashboard
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/12500/fc7950bd0cc6323bcc2d62b03e31c99edc7450b0ef76f9cbfa5133b527b25269.png" alt="Dashboard di rilevamento delle minacce — statistiche, cronologia di 7 giorni, registro minacce in tempo reale, IP principali responsabili e minacce per paese" width="100%">
</p>
Il pacchetto include una dashboard integrata in modalità scura (Alpine.js + Tailwind CDN — nessun passaggio di build richiesto).```
+-------------------------------------------------------------------------+
| Threat Detection Dashboard |
+-------------------------------------------------------------------------+
| Total: 847 | High: 23 | Med: 156 | Low: 668 | IPs: 94 |
+-------------------------------------------------------------------------+
| [Timeline Chart - 7 Day Stacked Bar] |
+-------------------------------------------------------------------------+
| Search: [___________] Level: [All] |
| Time IP Type Level Confidence Actions |
| Mar 2 14:02 185.220.101.4 SQL Injection HIGH 80% [FP] |
| Mar 2 13:58 45.33.32.156 XSS Script Tag HIGH 65% [FP] |
| Mar 2 13:45 192.168.1.10 Scanner: Nikto MED 35% [FP] |
+-------------------------------------------------------------------------+
| Top IPs | Threats by Country |
| 185.220.101.4 [23] | US 234 |
| 45.33.32.156 [18] | CN 156 |
| 103.152.220.1 [12] | RU 98 |
+-------------------------------------------------------------------------+
Aggiungi a .env:```env
THREAT_DETECTION_DASHBOARD=true
Visita: `http://your-app.test/threat-detection`
### Accesso durante lo sviluppo locale
La dashboard utilizza di default il middleware `['web', 'auth']`, quindi gli utenti devono aver effettuato l'accesso. Se la tua applicazione non dispone ancora di autenticazione, limitala invece alla tua macchina:```env
THREAT_DETECTION_DASHBOARD_GUARD=ip
THREAT_DETECTION_DASHBOARD_IPS=127.0.0.1
Tutte le opzioni di guard, e la guard separata sugli endpoint che disabilitano le rilevazioni, sono trattate in Dashboard e autenticazione API.
Se la dashboard mostra dati vuoti, la pagina è stata caricata ma le sue chiamate API non sono riuscite. Vedi Autenticazione API.
Il pacchetto fornisce 15 endpoint REST per creare dashboard personalizzate o integrazioni.
Le rotte API utilizzano il middleware auth:sanctum per impostazione predefinita. Il pacchetto gestisce questo in modo elegante:
['api'] soltanto. L'API funziona senza autenticazione.Se non usi Sanctum ma vuoi proteggere la tua API, hai due opzioni:
Opzione 1 - Usa la guard di autenticazione integrata:```env THREAT_DETECTION_API_GUARD=auth
**Opzione 2 - Modificare direttamente il middleware:**```php
// config/threat-detection.php
'api' => [
'enabled' => true,
'prefix' => 'api/threat-detection',
'middleware' => ['api', 'auth'], // or 'auth:your-guard'
],
Per test locali (se Sanctum blocca l'accesso), modifica temporaneamente:```php 'middleware' => ['api'], // remove 'auth:sanctum'
> Ripristina l'autenticazione prima di distribuire in produzione.
### Riferimento Endpoint
| Metodo | Endpoint | Descrizione |
|--------|----------|-------------|
| GET | `/api/threat-detection/threats` | Elenca le minacce (paginato, filtrabile) |
| GET | `/api/threat-detection/threats/{id}` | Dettagli di una singola minaccia |
| POST | `/api/threat-detection/threats/{id}/false-positive` | Contrassegna la minaccia come falso positivo |
| GET | `/api/threat-detection/stats` | Statistiche generali |
| GET | `/api/threat-detection/summary` | Ripartizione dettagliata per tipo, livello, IP |
| GET | `/api/threat-detection/live-count` | Minacce nell'ultima ora |
| GET | `/api/threat-detection/by-country` | Raggruppate per paese |
| GET | `/api/threat-detection/by-cloud-provider` | Raggruppate per provider cloud |
| GET | `/api/threat-detection/top-ips` | IP principali responsabili |
| GET | `/api/threat-detection/timeline` | Cronologia delle minacce (per grafici) |
| GET | `/api/threat-detection/ip-stats?ip=x.x.x.x` | Statistiche per IP specifico |
| GET | `/api/threat-detection/correlation` | Analisi di correlazione |
| GET | `/api/threat-detection/export` | Esporta in CSV |
| GET | `/api/threat-detection/exclusion-rules` | Elenca le regole di esclusione |
| DELETE | `/api/threat-detection/exclusion-rules/{id}` | Elimina una regola di esclusione |
### Parametri di Query per `/threats`
| Parametro | Descrizione |
|-----------|-------------|
| `keyword` | Cerca in IP, URL, tipo |
| `ip` | Filtra per indirizzo IP |
| `level` | Filtra per livello di minaccia (`high`, `medium`, `low`) |
| `type` | Filtra per tipo di minaccia |
| `country` | Filtra per codice paese |
| `is_foreign` | Filtra IP esteri (`true`/`false`) |
| `cloud_provider` | Filtra per provider cloud |
| `is_false_positive` | Filtra per stato di falso positivo (`true`/`false`) |
| `date_from` / `date_to` | Filtro intervallo di date |
| `per_page` | Elementi per pagina (predefinito: 20, massimo: 100) |
### Esempio di Risposta API
**GET `/api/threat-detection/stats`:**```json
{
"success": true,
"data": {
"total_threats": 847,
"high_severity": 23,
"medium_severity": 156,
"low_severity": 668,
"unique_ips": 94,
"foreign_ips": 67,
"cloud_attacks": 12,
"today": 34,
"last_hour": 5
}
}
Vue.js:```javascript async mounted() { const response = await fetch('/api/threat-detection/stats'); this.stats = await response.json();
const threats = await fetch('/api/threat-detection/threats?per_page=20');
this.threats = await threats.json();
}
**React:**```jsx
useEffect(() => {
fetch('/api/threat-detection/stats')
.then(res => res.json())
.then(data => setStats(data));
}, []);
Se la tua API utilizza
auth:sanctum, includi le intestazioni di autenticazione o configura l'autenticazione SPA di Sanctum per le richieste basate su cookie.
php artisan threat-detection:doctor
php artisan threat-detection:stats
php artisan threat-detection:enrich --days=7
php artisan threat-detection:purge --days=30
php artisan threat-detection:export-fail2ban --level=high --since=24h --min-hits=5 php artisan threat-detection:export-fail2ban --format=plain > /tmp/banlist.txt
php artisan threat-detection:export-blocklist --format=nginx > /etc/nginx/blocklist.conf php artisan threat-detection:export-blocklist --format=apache > .htaccess-deny php artisan threat-detection:export-blocklist --format=csv --since=7d
---
## Agire sui Dati (Blocco Lato Operatore)
Il pacchetto non blocca mai una richiesta — questa è la sua identità, non un'impostazione predefinita. Le esportazioni sopra
alimentano i livelli di enforcement che già esegui (fail2ban, nginx, un WAF perimetrale). Ma alcune distribuzioni
non hanno alcun livello di questo tipo da alimentare — hosting condiviso, PaaS, container dietro un load balancer che
non controlli. Per quelle, il pacchetto espone le sue *decisioni* come helper, e scrivi tu il
middleware di enforcement. Stessa architettura delle esportazioni: **forniamo noi
l'intelligence, fornisci tu il rifiuto.**```php
// app/Http/Middleware/EnforceThreatDecisions.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use JayAnta\ThreatDetection\Facades\ThreatDetection;
class EnforceThreatDecisions
{
public function handle(Request $request, Closure $next)
{
$ip = (string) $request->ip();
// Static operator denylist (config: blocklisted_ips).
// CIDR supported; whitelisted_ips wins on overlap.
if (ThreatDetection::isBlocklisted($ip)) {
abort(403);
}
// Volumetric flood: refuse over-threshold clients until the window resets.
if (ThreatDetection::isDdosThresholdExceeded($ip)) {
return response('Too Many Requests', 429, [
'Retry-After' => (string) config('threat-detection.ddos.window', 60),
]);
}
return $next($request);
}
}
Prima di applicare l'enforcement su IP, configura
TrustProxies.Tutto quanto sopra si basa su
$request->ip(). Dietro un load balancer, una CDN o un reverse proxy, questo restituisce l'IP client solo quando Laravel sa quali proxy considerare attendibili. Se non lo sa, due cose si rompono contemporaneamente: ogni richiesta sembra provenire dal proxy, quindi una voce in denylist blocca tutto il tuo traffico o nessuna parte di esso — e peggio, se l'app si fida di un header inoltrato che non dovrebbe, un attaccante impostaX-Forwarded-Fore aggira direttamente la blocklist.Questo conta più qui che per
whitelisted_ips. Una corrispondenza errata nella whitelist significa solo che il pacchetto analizza una richiesta che avrebbe potuto saltare: fallisce in modo sicuro. Una denylist usata per rifiutare il traffico fallisce in modo aperto — credi che un indirizzo sia bloccato quando non lo è. Controllaapp/Http/Middleware/TrustProxies.php(o la chiamatatrustProxiesinbootstrap/app.phpsu Laravel 11+) prima di fare affidamento su uno dei due helper per l'enforcement.
Registralo globalmente (prima del middleware di rilevamento va bene — gli helper leggono config e cache, non dipendono dall'ordine dei middleware):```php // bootstrap/app.php (Laravel 11+) ->withMiddleware(function ($middleware) { $middleware->prepend(\App\Http\Middleware\EnforceThreatDecisions::class); })
Gli helper:
| Helper | Restituisce | Basato su |
|---|---|---|
| `ThreatDetection::isBlocklisted($ip)` | `bool` | config `blocklisted_ips` (CIDR tramite `IpUtils`; la whitelist ha la precedenza) |
| `ThreatDetection::isWhitelisted($ip)` | `bool` | config `whitelisted_ips` |
| `ThreatDetection::ddosRequestCount($ip)` | `int` | il contatore di flood che il middleware di rilevamento mantiene |
| `ThreatDetection::isDdosThresholdExceeded($ip)` | `bool` | quel contatore rispetto a `ddos.threshold` |
Note:
- **La denylist è statica e gestita dall'operatore.** Nulla nel pacchetto vi aggiunge mai
elementi — esegue la stessa decisione che prenderebbe una jail di fail2ban ("ho letto la dashboard; questo /24
è ostile"), solo in-app.
- Il contatore DDoS conta solo le richieste che hanno raggiunto il rilevamento (`skip_paths`, IP
in whitelist e ambienti disabilitati non vengono mai contati) e resta a 0 sui driver di cache
dove il rilevamento DDoS è disabilitato (`file`, `database`, `null`).
- Quando un client supera la soglia, viene anche inviato un evento [`DdosThresholdExceeded`](#ddosthresholdexceeded-event)
— utile per l'alerting o per alimentare una lista di ban esterna. Non chiamare `abort()`
dal listener, però: i listener vengono eseguiti all'interno del `try/catch` fail-open del
middleware di rilevamento, quindi il rifiuto spetta al tuo middleware come sopra.
---
## Tracciamento dei Probe 404
Il pacchetto rileva i probe di ricognizione — bot che colpiscono percorsi vulnerabili noti come `/wp-admin`, `/.env` o `/phpmyadmin` sul tuo sito che non è WordPress né phpMyAdmin. Questi non hanno payload dannoso; il percorso stesso è il segnale.
Vengono registrati con un tag di tipo `[probe]`, separato dal rilevamento basato su payload. Se una richiesta di probe contiene anche un payload dannoso, entrambi vengono registrati in modo indipendente.
Abilitato per impostazione predefinita con oltre 50 percorsi di probe. Personalizzabile in `config/threat-detection.php`:```php
'probe_tracking' => [
'enabled' => true,
'default_level' => 'medium',
'paths' => [
'/wp-admin' => 'WordPress Admin',
'/wp-admin/*' => 'WordPress Admin',
'/.env' => 'Environment File',
'/phpmyadmin' => 'phpMyAdmin',
'/actuator/*' => 'Spring Actuator',
// Add your own probe paths...
],
],
Disattiva con THREAT_DETECTION_PROBE_TRACKING=false.
Se specifici campi di modulo contengono legittimamente HTML, parole chiave SQL o codice (ad es., editor CMS, input di frammenti di codice), puoi escluderli dalla scansione:```php // config/threat-detection.php 'safe_fields' => ['content', 'body', 'html', 'description', 'code'],
I campi elencati qui vengono rimossi dai parametri di query e dal corpo della richiesta - sia form-encoded che JSON (`application/json`) - prima che venga eseguito il rilevamento. Gli altri campi sulla stessa richiesta vengono comunque scansionati completamente.
### Percorsi sicuri (path-aware, per API JSON annidate)
`safe_fields` corrisponde a un nome di chiave **ovunque** appaia. Per API JSON annidate spesso è troppo ampio - potresti voler esentare il valore di un campo specifico senza esentare quella chiave ovunque. Usa `safe_paths`, che corrisponde per **percorso** in notazione a punti e supporta i caratteri jolly `fnmatch`:```php
// config/threat-detection.php
'safe_paths' => ['search.query', 'filters.*.value'],
Per esempio, search.query esenta il valore di {"search": {"query": "..."}} (una casella di ricerca il cui testo contiene legittimamente parole come SELECT), mentre un campo query in qualsiasi altro punto della richiesta viene comunque scansionato. Tutto ciò che non è elencato viene scansionato esattamente come prima.
Una regex da sola non può esprimere ogni vincolo: qualsiasi sequenza di 12 cifre corrisponde al pattern Aadhaar, ma un vero numero Aadhaar supera anche il checksum Verhoeff. Associa un'etichetta di pattern (predefinita o personalizzata) a un validatore nominato e un hit regex conta come rilevamento solo quando almeno un valore corrispondente lo supera:```php // config/threat-detection.php 'pattern_validators' => [ 'Aadhaar Number Detected' => 'verhoeff', // shipped default ],
Validatori disponibili:
| Validator | Checksum | Uso tipico |
|------------|----------|-------------|
| `verhoeff` | Verhoeff | Numeri Aadhaar |
| `luhn` | Luhn | Numeri di carte di credito/debito |
Con la mappatura inclusa, timestamp, ID ordine e codici a barre che risultano essere lunghi 12 cifre non vengono più registrati come PII — mentre i veri numeri Aadhaar lo sono ancora. Se più valori corrispondono e solo uno supera il checksum, il rilevamento scatta comunque: un numero reale tra il rumore è comunque una fuga di dati.
Abbina un validator al tuo pattern personalizzato per il rilevamento delle carte con controllo del checksum:```php
'custom_patterns' => ['/\b(?:\d[ -]?){13,19}\b/' => 'Card Number Detected'],
'pattern_validators' => ['Card Number Detected' => 'luhn'],
An unknown validator name fails open — the match is counted unvalidated and a warning is logged once — so a typo can never silently disable a detection pattern. Configs published before this feature simply don't have the key and keep their exact current behaviour.
Rilevare dati sensibili significava memorizzarli. Un modulo di profilo con un numero di cellulare, un PAN e un conto bancario attiverebbe tre pattern PII, e ciascuna delle tre righe scritte conservava l'intero corpo della richiesta parola per parola - trattenuto per l'intero periodo di conservazione, leggibile da chiunque avesse accesso alla dashboard o al database. Un valore in una query string finiva anche nella colonna url. Il rilevatore diventava una seconda copia concentrata di esattamente ciò di cui ti mette in guardia.
Attivo per impostazione predefinita dalla v1.7.0. Quando un pattern il cui label è elencato viene attivato, il valore che ha trovato viene mascherato nel payload e nell'URL memorizzati:``` BODY: {"name":"Jane Doe","mobile":"[REDACTED]","pan":"[REDACTED]","bank_account":"[REDACTED]"}
L'avviso, l'endpoint, i nomi dei campi e l'IP attaccante sopravvivono tutti: solo il valore viene rimosso. La redazione viene eseguita *dopo* il rilevamento, quindi non viene perso nulla.```php
// config/threat-detection.php
'redact' => [
'enabled' => env('THREAT_DETECTION_REDACT', true),
'mask' => '[REDACTED]',
'labels' => ['Aadhaar Number Detected', 'PAN Number Detected', /* ... */],
],
Attack payload sono deliberatamente lasciati intatti: una stringa di injection è una prova, non un segreto, e mascherarla distruggerebbe l’indagine. Vengono toccati solo i label che elenchi.
Questo non sostituisce Safe Fields. Questi impediscono che un campo venga scansionato; la redazione ti consente di continuare a scansionare e di smettere di memorizzare. Imposta
THREAT_DETECTION_REDACT=falsese hai bisogno dei payload completi per la forensics.
La dashboard e l’API supportano guardie di autenticazione configurabili tramite .env:```env
THREAT_DETECTION_DASHBOARD_GUARD=auth
THREAT_DETECTION_DASHBOARD_GUARD=role THREAT_DETECTION_DASHBOARD_ROLE=admin
THREAT_DETECTION_DASHBOARD_GUARD=ip THREAT_DETECTION_DASHBOARD_IPS=127.0.0.1,10.0.0.0/8
Le stesse opzioni sono disponibili per le route API con `THREAT_DETECTION_API_GUARD`.
Quando `guard=none` (predefinito), il pacchetto registra un avviso una volta al giorno per ricordarti di configurare l'autenticazione.
La guardia **fallisce in modalità chiusa**: un valore di guardia non riconosciuto (ad esempio un refuso) viene negato con un 403 e un avviso registrato, piuttosto che concedere silenziosamente l'accesso, e `guard=role` nega (con un avviso) quando il modello utente autenticato non ha un metodo `hasRole()`.
### Disattivare un rilevamento richiede più del solo accesso in lettura
Contrassegnare una minaccia come falso positivo ed eliminare una regola di esclusione silenziano entrambi un tipo di rilevamento per tutti, il che è un privilegio diverso dalla lettura del registro. Questi due endpoint vengono controllati rispetto a una guardia separata:```env
# Options: none, auth, role, ip. Default: role
THREAT_DETECTION_API_WRITE_GUARD=role
Si applica solo a quelle rotte, quindi la lettura e la dashboard si comportano esattamente come specificato da THREAT_DETECTION_API_GUARD. Senza di esso, qualsiasi utente autenticato della tua applicazione potrebbe disattivare un rilevamento.
Se il tuo modello utente non ha hasRole(), usa =auth. Per ripristinare il comportamento precedente alla versione 1.7.0, in cui qualsiasi utente autenticato poteva disabilitare i rilevamenti, usa =none - threat-detection:doctor mostrerà un avviso quando è impostato così.
Nota Dashboard ↔ API: la dashboard integrata recupera i suoi dati dalle rotte API utilizzando il cookie di sessione del browser. Se le tue rotte API sono protette con
auth:sanctum, configura l'autenticazione Sanctum stateful/SPA (oppure punta la dashboard verso un guard autenticato tramite cookie) affinché quelle chiamate AJAX siano autorizzate - altrimenti la dashboard viene renderizzata vuota.
Aggiungi i tuoi pattern regex di rilevamento in config/threat-detection.php:```php
'custom_patterns' => [
'/your-regex-here/i' => 'Your Threat Label',
],
**Esempio - rilevare una sonda verso un endpoint admin personalizzato:**```php
'/\/my-admin-panel/i' => 'Custom Admin Panel Probe',
Oltre alla classica forma stringa, il valore di un pattern può essere un array per un controllo completo:```php 'custom_patterns' => [ '/\b(?:\d[ -]?){13,19}\b/' => [ 'label' => 'Card Number Detected', // required 'level' => 'high', // low|medium|high — overrides keyword derivation 'contexts' => ['query', 'body'], // query|body|headers — default: all segments 'validator' => 'luhn', // post-match checksum, wins over pattern_validators ], ],
- **`level`** imposta direttamente il livello di minaccia invece di derivarlo dalle parole chiave `threat_levels` nell'etichetta.
- **`contexts`** limita la scansione a segmenti specifici della richiesta — ad esempio, un pattern di carta che ha senso solo nel corpo smette di corrispondere a sequenze di cifre negli header.
- **`validator`** indica un controllo post-corrispondenza inline (vedi [Validatori Post-Corrispondenza](#post-match-validators-checksum-aware-false-positive-reduction)); ha precedenza sulla mappa delle etichette `pattern_validators`.
Le voci stringa e array si mescolano liberamente nella stessa configurazione. Le opzioni malformate **falliscono in modo aperto** — il pattern esegue comunque la scansione, senza restrizioni, e viene registrato un avviso — quindi un errore di configurazione non può mai disabilitare o restringere silenziosamente una rilevazione.
> **Nota:** I percorsi di probe comuni come `/wp-login.php`, `/.env`, `/phpmyadmin` sono ora gestiti automaticamente dalla funzionalità [Tracciamento Probe 404](#404-probe-tracking). Non servono pattern personalizzati per quelli.
Il livello di minaccia per ogni pattern è determinato automaticamente confrontando le parole chiave nell'etichetta con la configurazione `threat_levels`:```php
'threat_levels' => [
'high' => ['XSS', 'SQL Injection', 'SQL DDL', 'SQL DML', 'SQL File', 'SQL Hex', 'RCE', ..., 'Shellshock', 'Spring4Shell', 'PowerShell', 'CRLF', 'Null Byte', 'SSTI', 'Java', 'LDAP', 'XPath', 'PHP assert', ...],
'medium' => ['Directory Traversal', 'LFI', 'SSRF', 'Sensitive', 'Config', ..., 'Open Redirect', 'LF Injection', 'GraphQL', 'Spring Boot Actuator', ...],
'low' => ['User-Agent', 'JS Redirect', 'SEO Bot', 'Empty', 'Rate', 'Command-line Downloader', 'DNS Rebinding'],
],
Se l'etichetta non corrisponde a nessuna parola chiave, la minaccia viene impostata per impostazione predefinita su gravità low.
I pattern regex non validi vengono automaticamente saltati e registrati come avvisi: non causeranno il crash dell'applicazione.
Per l'accesso programmatico ai dati sulle minacce al di fuori del middleware:```php use JayAnta\ThreatDetection\Facades\ThreatDetection;
// Get attack statistics for a specific IP $stats = ThreatDetection::getIpStatistics('192.168.1.1');
// Detect coordinated attacks (multiple IPs targeting same URL within 15 minutes) $attacks = ThreatDetection::detectCoordinatedAttacks(15, 3);
// Detect attack campaigns (same threat type from 5+ IPs in last 24 hours) $campaigns = ThreatDetection::detectAttackCampaigns(24);
// Get a summary of all correlation data $summary = ThreatDetection::getCorrelationSummary();
// Operator-side decision helpers (see "Acting on the Data") $blocked = ThreatDetection::isBlocklisted('203.0.113.7'); // static denylist, CIDR, whitelist wins $trusted = ThreatDetection::isWhitelisted('10.0.0.5'); $count = ThreatDetection::ddosRequestCount('203.0.113.7'); // requests in the current DDoS window $flooded = ThreatDetection::isDdosThresholdExceeded('203.0.113.7');
---
## Passaggio alla Produzione
Il pacchetto è passivo per progettazione: non blocca, rifiuta o altera mai una richiesta, e il middleware di rilevamento avvolge l'intero corpo in `try/catch`, quindi un errore di rilevamento non può mai compromettere la tua applicazione. Include impostazioni predefinite sensate e non richiede servizi esterni per funzionare. Prima di andare in produzione, vale la pena dare un'occhiata a questa breve checklist:
1. **Proteggi dashboard e API.** Entrambe usano di default `guard = none` per un primo avvio senza configurazione e registrano un avviso giornaliero mentre sono non protette. Prima della produzione, imposta un guard: `THREAT_DETECTION_DASHBOARD_GUARD` e `THREAT_DETECTION_API_GUARD` (`auth`, `role` o `ip`). Un valore non riconosciuto o un guard `role` su un modello utente senza `hasRole()` ora **fallisce in modo chiuso** (403), quindi un refuso non esporrà silenziosamente i dati. La disattivazione di un rilevamento è gestita separatamente da `THREAT_DETECTION_API_WRITE_GUARD`, che di default è `role`. Vedi [Autenticazione di Dashboard e API](#dashboard-and-api-authentication).
2. **Esegui le migrazioni** (`vendor:publish --tag=threat-detection-migrations && migrate`). La ripubblicazione è sicura: le migrazioni già pubblicate vengono saltate.
3. **Scegli una modalità di rilevamento.** `balanced` (predefinita) si adatta alla maggior parte delle app; usa `relaxed` per siti ricchi di contenuti, `strict` per superfici ad alta sicurezza. Ottimizza con `content_paths`, `safe_fields` e `min_confidence`: vedi [Riduzione dei Falsi Positivi](#reducing-false-positives).
4. **Rivedi i pattern PII regionali / personalizzati.** I valori predefiniti sono incentrati sull'India (Aadhaar, PAN, IFSC) e i pattern numerici ampi (es. conto bancario) possono corrispondere a lunghi ID numerici al di fuori delle rotte autenticate. Sostituisci o riduci `custom_patterns` per la tua regione e app, e aggiungi rotte con contenuti pesanti a `auth_paths` / `content_paths`.
5. **Attiva la conservazione** se prevedi volume: `THREAT_DETECTION_RETENTION=true` (pulizia automatica tramite lo scheduler). Richiede che lo scheduler di Laravel (`schedule:run`) sia guidato da cron.
6. **Extra opzionali, tutti disattivati di default:** avvisi Slack (`THREAT_DETECTION_NOTIFICATIONS`), arricchimento geo (`php artisan threat-detection:enrich` - l'unica funzionalità che effettua una chiamata in uscita, al gratuito ip-api.com) e scritture in coda (`THREAT_DETECTION_QUEUE` - abilita solo se esegui già un worker di coda; altrimenti le scritture sono sincrone e non richiedono Redis).
Nessun Redis, nessun worker di coda e nessuna chiamata di rete in uscita sono richiesti per il rilevamento e la registrazione principali.
---
## Riduzione dei Falsi Positivi
Il pacchetto fornisce diversi strumenti per ridurre i falsi positivi. Usa quelli che si adattano alla tua situazione:
### Campi e Percorsi Sicuri
Escludi un campo dalla scansione completamente, sia per nome ovunque (`safe_fields`) sia tramite percorso in notazione a punti per JSON annidati (`safe_paths`). L'approccio più semplice e il più drastico: il campo viene saltato, quindi nessun rilevamento viene eseguito su di esso.
Dettagli completi ed esempi: [Campi Sicuri](#safe-fields-false-positive-reduction).
### Soppressione dei Percorsi di Contenuto
Se hai editor CMS, moduli di post di blog o sezioni di commenti in cui gli utenti inviano contenuti ricchi, quei percorsi spesso generano falsi positivi (es. un post di blog contenente esempi di codice `<script>`). Aggiungi quei percorsi per sopprimere gli avvisi bassi/medi:```php
// config/threat-detection.php
'content_paths' => [
'admin/posts/*',
'admin/pages/*',
'blog/*/edit',
'comments',
],
Su questi percorsi, vengono registrate solo le minacce ad alta gravità.
Fai clic sul pulsante FP su qualsiasi minaccia nella dashboard per contrassegnarla come falso positivo. Questa azione:
is_false_positive = trueGestisci le regole di esclusione tramite API:```bash GET /api/threat-detection/exclusion-rules DELETE /api/threat-detection/exclusion-rules/{id}
### Punteggio di Confidenza
Ogni minaccia riceve un punteggio di confidenza (0-100) basato su:
- Numero di corrispondenze di pattern nella stessa richiesta
- Gravità del pattern corrispondente
- Dove è stato trovato il pattern (query string > header > body)
- Se lo user-agent corrisponde a uno strumento di attacco noto
- Modalità di rilevamento corrente
Le minacce al di sotto della soglia di confidenza per la tua modalità di rilevamento non vengono registrate (vedi [Modalità di Rilevamento](#detection-modes)).
---
## Tipi di Attacco Rilevati
| Categoria | Esempi |
|----------|---------|
| **SQL Injection** | UNION, boolean, time-based, codifica CHAR, DDL (DROP/ALTER/CREATE), DML (INSERT/UPDATE/DELETE), operazioni su file (INTO OUTFILE, LOAD_FILE), enumerazione ORDER BY, stringhe hex, UNHEX |
| **NoSQL Injection** | Operatori MongoDB $ne, $gt, $regex, $where |
| **XSS** | Tag script, gestori di eventi SVG (`<svg onload=`), gestori di eventi HTML (`<body onload=`, `<img onerror=`), espressioni CSS, URI JavaScript, manipolazione DOM |
| **Esecuzione di Codice** | Funzioni shell RCE, deserializzazione PHP, deserializzazione Java (base64 + magic bytes hex), template injection (Blade, JSP, ASP, Jinja2, Velocity), eval(), decodifica base64, assert() PHP, create_function(), preg_replace /e |
| **SSTI** | Sonde matematiche (`{{7*7}}`), import/config Jinja2, template Velocity, Expression Language |
| **Command Injection** | Linux (funzioni shell, catene di comandi, curl, wget, nc), Windows (cmd.exe, PowerShell, wscript, cscript, net user) |
| **Accesso ai File** | Directory traversal, protocolli LFI/RFI, sonde su file sensibili (.env, .git, composer.json) |
| **SSRF** | Localhost (127.0.0.1, 0.0.0.0, ::1), metadati AWS/GCP, IP privati, localhost codificato hex/decimale, DNS rebinding (xip.io, nip.io, sslip.io) |
| **LDAP Injection** | Manipolazione di filtri LDAP, OR injection |
| **XPath Injection** | Selettori di attributi, funzioni XPath (contains, substring) |
| **CRLF / Header Injection** | CRLF codificato in URL (`%0d%0a`), LF injection, null byte injection |
| **Attacchi di Protocollo** | HTTP request smuggling (CL+TE), SSI injection |
| **Exploit CVE** | Shellshock (CVE-2014-6271), Spring4Shell (CVE-2022-22965), PHPUnit RCE (CVE-2017-9841), Drupalgeddon, Log4Shell |
| **Tracciamento Sonde** | WordPress (`/wp-admin`, `/wp-login.php`), file di configurazione (`/.env`, `/.git`), strumenti di database (`/phpmyadmin`), sonde tecnologiche (`.asp`, `.jsp`), Spring actuator, documentazione Swagger/API - oltre 50 percorsi |
| **Scanner** | SQLMap, Nikto, Nmap, Burp Suite, FeroxBuster, FFUF, XSStrike, Dalfox, Netsparker, Qualys, Nuclei e oltre 20 altri (53 in totale) |
| **AI Scraper** | GPTBot, ClaudeBot, ChatGPT, ByteSpider, Cohere, Common Crawl |
| **Browser Headless** | HeadlessChrome, PhantomJS, Selenium, Puppeteer, Playwright |
| **Bot** | Script Python, client HTTP Go, cURL, wget, AhrefsBot, SEMRushBot, user agent vuoti |
| **Autenticazione** | Rilevamento brute force, perdite di token, esposizione di password, esposizione di ID sessione |
| **DDoS** | Rilevamento di richieste eccessive basato su frequenza |
| **Evasione** | Inserimento di commenti SQL, doppia codifica URL, codifica entità HTML, escape Unicode, IIS Unicode, escape hex |
| **Altro** | Introspection GraphQL, prototype pollution, open redirect, XXE, web shell, crypto mining, rilevamento PII |
---
## Esecuzione della Suite di Test```bash
composer test
Il pacchetto include 335 test (856 asserzioni) che coprono pattern di rilevamento, comportamento del middleware, endpoint API, punteggio di confidenza, regole di esclusione, rilevamento DDoS, resistenza all'evasione, pattern CVE, iniezione LDAP/XPath/SSTI, rilevamento bot/scanner, tracciamento delle sonde, comandi di esportazione, autenticazione della dashboard, campi sicuri, ottimizzazioni delle prestazioni e verifica completa del ciclo HTTP-to-DB.
Licenza MIT. Consulta LICENSE per i dettagli.
I contributi sono benvenuti! Invia una Pull Request.