Torna agli aggiornamenti
New releaseSep 3, 2026

laravel-threat-detection v1.7.2

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.

Condividi

Latest Version Tests PHPStan Level 5 Code Style Pint Total Downloads PHP Version License

Rilevamento Minacce Laravel

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.

Installa il pacchetto, invia tre attacchi — SQL injection, directory traversal, XSS — tutti restituiscono HTTP 200 perché nulla viene bloccato, e tutti e tre sono già conteggiati in threat-detection:stats

Sei qui perché hai visto qualcosa del genere?```

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

2. Pubblica le migrazioni ed eseguile

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_logs non esisterà e tutte le rilevazioni andranno perse silenziosamente (vedrai solo errori in storage/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.

3. Registrare il middleware

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,
    ],
];

4. (Opzionale) Pubblica il file di configurazione```bash

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

Passaggio 2: apri un URL di test nel browser

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

Funzionalità

  • 150+ Pattern di Rilevamento - SQL injection (UNION, DDL, DML, operazioni su file), XSS (script, SVG, espressioni CSS), RCE, directory traversal, SSRF, XXE, Log4Shell, NoSQL injection, command injection (Linux + Windows), LDAP injection, XPath injection, SSTI, CRLF injection, deserializzazione Java e altro
  • 83 Firme di Bot/Scanner - SQLMap, Nikto, Nmap, Burp Suite, FeroxBuster, FFUF, XSStrike, Dalfox, Netsparker e oltre 70 altre firme di scanner e bot
  • Rilevamento AI Scraper - GPTBot, ClaudeBot, ByteSpider, Common Crawl e altri bot di addestramento AI
  • Rilevamento Browser Headless - HeadlessChrome, PhantomJS, Selenium, Puppeteer, Playwright
  • Tracciamento Sonde 404 - Rileva sonde di ricognizione che colpiscono percorsi vulnerabili noti (/wp-admin, /.env, /phpmyadmin, /actuator, ecc.) con oltre 50 percorsi di sonda predefiniti
  • Monitoraggio DDoS - Rilevamento di soglie basato su frequenza con finestre configurabili
  • Punteggio di Confidenza - Ogni minaccia riceve un punteggio di confidenza da 0 a 100 basato su numero di pattern, contesto e segnali
  • Resistenza all'Evasione - Pipeline di normalizzazione neutralizza l'inserimento di commenti SQL, doppia codifica URL, codifica di entità HTML, escape Unicode ed escape esadecimali prima del matching dei pattern
  • Rilevamento CVE - Shellshock (CVE-2014-6271), Spring4Shell (CVE-2022-22965), PHPUnit RCE (CVE-2017-9841), Drupalgeddon, Log4Shell
  • Rilevamento Sensibile al Contesto - I pattern trovati nelle query string ottengono un punteggio più alto rispetto a quelli nel corpo della richiesta
  • Scansione del Corpo della Richiesta - Vengono ispezionati sia i corpi delle richieste form-encoded che JSON (application/json)
  • Campi Sicuri - Escludi specifici campi di modulo dalla scansione (per editor CMS, input di codice, campi di ricerca)
  • Segnalazione Falsi Positivi - Segnala le minacce come falsi positivi dalla dashboard; crea automaticamente regole di esclusione
  • Tre Modalità di Rilevamento - strict, balanced (predefinita) e relaxed - sensibilità regolabile
  • Soppressione Percorsi di Contenuto - Whitelist dei percorsi CMS/blog per sopprimere avvisi bassi/medi da contenuti ricchi
  • Rilevamento PII - Pattern di esposizione di dati sensibili (configurabili per regione)
  • Arricchimento Geografico - Identificazione di paese, città, ISP e provider cloud tramite API gratuita
  • Avvisi Slack - Notifiche in tempo reale per minacce ad alta gravità (funziona su Laravel 10 e 11+)
  • Dashboard Integrata - Dashboard Blade in modalità scura (Alpine.js + Tailwind CDN, zero passaggi di build)
  • Guardia di Autenticazione Dashboard - Autenticazione configurabile per dashboard e API (nessuna, auth, ruolo o basata su IP)
  • 15 Endpoint API - API REST completa per creare dashboard Vue/React/mobile personalizzate
  • Esportazione Fail2ban - Esporta gli IP rilevati in formato compatibile con fail2ban o come blocklist semplice
  • Esportazione Blocklist - Esporta gli IP in formato nginx deny, Apache deny, CSV o semplice
  • Esportazione CSV - Esportazione dei log delle minacce con un clic (fino a 10.000 righe)
  • Analisi di Correlazione - Rileva attacchi coordinati e campagne di attacco tra più IP
  • Ottimizzato per le Prestazioni - Caricamento lazy dei pattern basato su categoria (esegue regex solo per le categorie di attacco pertinenti), uscita anticipata per richieste pulite, cortocircuito del browser UA (salta oltre 70 controlli per browser normali), lookup hash dei percorsi di sonda, inserimenti DB in batch, massimo di rilevamenti configurabile per richiesta
  • Agnostico rispetto al Database - MySQL, PostgreSQL, SQLite, SQL Server
  • Zero Configurazione - Funziona subito con impostazioni predefinite sensate
  • Sicuro per Progettazione - Il middleware intercetta i propri errori. Se il rilevamento fallisce, la tua app continua a funzionare. Le richieste non vengono mai bloccate.

Configurazione

Il pacchetto funziona senza alcuna modifica al file .env. Tutti i valori seguenti sono opzionali - aggiungili solo se vuoi sovrascrivere le impostazioni predefinite.```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).

Cleartext HTTP because ip-api.com's free tier rejects HTTPS; point this at

an HTTPS endpoint if you hold a key. Enrichment is opt-in either way.

THREAT_DETECTION_GEO_ENDPOINT=http://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

Dashboard auth guard (default: none)

Options: none, auth, role, ip

THREAT_DETECTION_DASHBOARD_GUARD=none

THREAT_DETECTION_DASHBOARD_ROLE=admin

THREAT_DETECTION_DASHBOARD_IPS=127.0.0.1

API auth guard (default: none - uses existing middleware config)

THREAT_DETECTION_API_GUARD=none

### 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).

Whitelisting delle rotte (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.

Auto-Purge (Criteri di conservazione)

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.

Evento DdosThresholdExceeded

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                                         |
+-------------------------------------------------------------------------+

Abilita la dashboard

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.


Endpoint API

Il pacchetto fornisce 15 endpoint REST per creare dashboard personalizzate o integrazioni.

Autenticazione API

Le rotte API utilizzano il middleware auth:sanctum per impostazione predefinita. Il pacchetto gestisce questo in modo elegante:

  • Sanctum installato: L'API richiede l'autenticazione tramite token Sanctum o autenticazione di sessione SPA.
  • Sanctum NON installato: Il pacchetto rileva automaticamente che Sanctum manca e ripiega su ['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
  }
}

Building Custom Frontends

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.


Comandi Artisan```bash

Check that detection is installed, wired up and actually recording.

Exits non-zero on a real failure, so it works in CI or a deploy step.

php artisan threat-detection:doctor

View threat stats summary in the terminal

php artisan threat-detection:stats

Enrich existing logs with geo-data (country, city, ISP, cloud provider)

Uses the free ip-api.com service (rate-limited to 45 req/min, auto-throttled)

php artisan threat-detection:enrich --days=7

Purge old logs to keep the database clean

php artisan threat-detection:purge --days=30

Export threat IPs for fail2ban (pipe to file or run directly)

php artisan threat-detection:export-fail2ban --level=high --since=24h --min-hits=5 php artisan threat-detection:export-fail2ban --format=plain > /tmp/banlist.txt

Export blocklist in various formats

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 imposta X-Forwarded-For e 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 è. Controlla app/Http/Middleware/TrustProxies.php (o la chiamata trustProxies in bootstrap/app.php su 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.


Campi Sicuri (Riduzione dei Falsi Positivi)

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.

Validatori Post-Match (Riduzione dei Falsi Positivi con Checksum)

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.


Redazione (Rilevare non significa memorizzare)

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=false se hai bisogno dei payload completi per la forensics.


Autenticazione di Dashboard e API

La dashboard e l’API supportano guardie di autenticazione configurabili tramite .env:```env

Options: none (default), auth, role, ip

THREAT_DETECTION_DASHBOARD_GUARD=auth

For role-based guard (Spatie compatible):

THREAT_DETECTION_DASHBOARD_GUARD=role THREAT_DETECTION_DASHBOARD_ROLE=admin

For IP-based guard:

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.


Pattern Personalizzati

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',

Forma array (opzioni per singolo pattern)

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.


Utilizzo della Facade

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à.

Segnalazione di Falsi Positivi

Fai clic sul pulsante FP su qualsiasi minaccia nella dashboard per contrassegnarla come falso positivo. Questa azione:

  1. Contrassegna la minaccia come is_false_positive = true
  2. Crea automaticamente una regola di esclusione, così che minacce simili provenienti dallo stesso URL/tipo vengano soppresse in futuro

Gestisci 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

Licenza MIT. Consulta LICENSE per i dettagli.

Contributi

I contributi sono benvenuti! Invia una Pull Request.

Crediti

Categorie