Passa al contenuto principale

Panoramica Sicurezza

La postura di sicurezza di Flo è revisionata con la metodologia OWASP Top 10:2025 su tre round. Questa pagina sintetizza le protezioni effettivamente presenti nel codice: autenticazione, rate limiting, header, segreti a riposo e audit/forense, seguite dalla cronologia delle remediation e dalle regole operative che mantengono la postura aggiornata.

Protezioni di autenticazione​

Login con password, login OTP e OIDC condividono lo stesso modello di sessione cookie. I flussi sono descritti in Autenticazione; i controlli rilevanti per la sicurezza sono:

  • Hashing password con BCrypt. La policy è minimo 8 caratteri e massimo 72 byte UTF-8 (troncamento BCrypt), più una blocklist offline di password comuni e violate che rifiuta anche le mutazioni classiche (Password1234, p@ssw0rd!). Vedi PasswordHelper e PasswordBlocklist.
  • Blocco login: 5 tentativi falliti attivano un blocco di 15 minuti per account. I contatori vivono nella tabella LoginAttempt, così container blue-green e riavvii di processo condividono un'unica vista; le righe stantie sono spazzate opportunisticamente e un login riuscito azzera il contatore.
  • Indurimento OTP: codici a 6 cifre, scadenza 10 minuti, 3 tentativi per codice, cooldown reinvio 30 s, confronto a tempo costante, hash a riposo e risposte identiche per email note e ignote (nessuna enumerazione).
  • Memorizzazione token: i token di reset password e conferma email sono memorizzati come hash, non in chiaro.
  • Protezioni di sessione: il cookie FloAuth è HttpOnly, Secure, SameSite=Lax e cifrato con Data Protection. Oltre alla scadenza scorrevole, AuthSessionService impone una durata assoluta di sessione di 7 giorni e invalidazione lato server (globale e per utente). Il logout revoca i refresh token OpenIddict e marca stantie le sessioni cookie; cambi e reset password invalidano le altre sessioni dell'utente.
  • Autorizzazione live: LoginAccessMiddleware ricontrolla policy di login e claim di ruolo dell'utente a ogni richiesta autenticata, riemettendo il cookie quando i privilegi a DB sono cambiati. Le password operatore seminate (seed) impongono un cambio password al primo login: la dashboard redirige alla pagina di cambio e l'API risponde 403 finché la password non è ruotata.
  • Mitigazioni enumerazione: una verifica BCrypt fittizia uniforma il percorso account-inesistente, e il recupero password restituisce un unico messaggio per hit e miss.

Rate limiting​

Il rate limiting è applicato a livello applicativo (policy rate limiter ASP.NET). Le policy principali:

PolicyPartizioneLimite
AuthEndpointsLimiterIP client20/min (login, registrazione, recupero; spento in Development)
PublicOtpValidateLimiterIP client10/min
PublicBrowserLimiterIP client60/min (form pubblici, richiesta OTP)
PublicIntegrationLimiterhash token (o IP)300/min
PaymentWebhookLimiterIP client120/min
BookingCheckoutLimiter / CommerceCheckoutLimiterutente (o IP)10/min
PresignRateLimiterutente120/min
MediaUploadRateLimiterhash token (o IP)120/min
PublicApiLimiterfinestra fissa10/min, 2 accodati

I rifiuti restituiscono 429 con errors.general.rateLimitExceeded. Le partizioni sono risolte da ClientIpResolver: l'header CF-Connecting-IP è onorato solo quando TRUST_CF_CONNECTING_IP è abilitato e il peer immediato è dentro il perimetro FORWARDED_PROXIES / FORWARDED_NETWORKS configurato, così un header falsificato non può creare partizioni fresche a quota piena. Lo stato limiter è in-process: oggi Flo gira con un'istanza backend per tenant, e lo scaling orizzontale richiederebbe un backing store condiviso.

Anche nginx.conf.template definisce zone limit_req per IP, ma la flotta di produzione gira su Docker + Traefik con i limiter applicativi; nginx è usato solo dal percorso Compose singolo-tenant/locale (esclusione documentata X-07).

Header e CSP​

Per i deploy nginx, nginx.conf.template imposta HSTS, Content-Security-Policy (default-src 'self', allow-list hash per script, frame-ancestors 'self'), X-Content-Type-Options, X-Frame-Options: SAMEORIGIN, Referrer-Policy, Permissions-Policy (geolocalizzazione, microfono, camera disabilitati) e X-Robots-Tag: noindex sulle API. Le location che dichiarano proprie add_header ripetono il set di sicurezza, perché in quel caso nginx scarta gli header ereditati.

La SPA Cloudflare Pages distribuisce Flo.FE/public/_headers con nosniff, X-Frame-Options, Referrer-Policy e Permissions-Policy. La CSP è differita per la SPA perché la pagina di login carica SDK terzi (Google Identity Services, Apple JS); il piano è distribuirla prima in Report-Only.

Le risposte API sono predefinite a no-store, il middleware eccezioni restituisce codici di errore localizzati senza stack trace, e il banner server è soppresso.

Segreti a riposo​

  • Segreti tenant: la CLI cifra i valori segreti nei file .env tenant con AES-256-GCM (tag autenticato, chiave derivata via scrypt), conservando il master.key a 0600. La rotazione è gestita da Rotazione dei Segreti.
  • Token auth webhook cifrati a riposo (ASP.NET Data Protection) e mai restituiti in chiaro.
  • Token API memorizzati come hash SHA-256 più prefisso di 8 caratteri; i binding presign contengono hash dei token, non il token grezzo.
  • Codici OTP e token di reset con hash a riposo; gli access token sono cifrati nello store OpenIddict.
  • Backup con sidecar .sha256 verificati prima di un ripristino; dump pre-deploy creati a ogni deploy.
  • Supply chain: immagini container fissate per digest in CI e nel Dockerfile, npm ci --ignore-scripts usato, dipendenze bloccate e un workflow SCA settimanale attivo.

Audit e forense​

La superficie completa è descritta in Impostazioni e Audit. Proprietà chiave:

  • La pista di audit è solo in accodamento: il DbContext rifiuta aggiornamenti ed eliminazioni delle righe AuditLog; le modifiche entità sono accodate nella stessa transazione della modifica con attore, azione, valori vecchi/nuovi e marca temporale.
  • La retention è predefinita a 730 giorni, configurabile tra 30 e 3650; le operazioni di anonimizzazione ed eliminazione accodano lapidi (tombstone) così il log resta auto-descrittivo dopo la redazione. Gli endpoint di export e anonimizzazione GDPR sono solo SuperAdmin.
  • Gli eventi auth (/api/v1/auth-events) registrano i fallimenti di login lato server e client mascherati; i fallimenti login con password e i blocchi sono registrati tramite la stessa giunzione. Il visualizzatore vive in Impostazioni > Accessi ed errori.
  • Log: file Serilog rotanti con visualizzatore solo SuperAdmin, export CSV/JSON con neutralizzazione formule foglio di calcolo, redazione token in query-string e PII mascherati nelle righe di log auth. Le richieste portano un header X-Correlation-ID per il tracing.

Cronologia remediation OWASP​

RoundObiettivoEsito
1 (2026-09-18)Superficie API backend + infra (Flo.BE/**, Dockerfile, compose, nginx, CI)41 finding, 4 critici (endpoint log anonimi, token Jarvis consolidato, credenziali SuperAdmin da seed, esposizione log); tutti corretti e riverificati dinamicamente
2 (2026-09-18)Approfondimento: Flo.FE/src/**, cli/src/**, Flo.SchemaGen/** + replay fix round-122 finding corretti (XSS/returnUrl/upload FE, segreti argv CLI/estrazione backup, permessi SchemaGen) e verificati
3 (2026-09-19)Audit profondo full-repo su HEAD 1e60ce1 + clone live anonimizzato40 finding su 10 domini (39 confermati, 1 parziale), 1 critico (token Strapi consolidato); fix chiusi in bugfix/owasp-security-fixes con suite verdi e 9/9 prove dinamiche

Fix notevoli del round-3: logout OIDC con revoca refresh token e sessioni lato server, token OTP/reset con hash a riposo, blocklist password, log auth mascherati e sink di log sanificati, blocco su DB condiviso tra container, cifratura token webhook, cap assoluto sessione 7 giorni, lapidi audit, trust dei forwarder da env FORWARDED_*, header di sicurezza Cloudflare Pages e immagini di deploy fissate per digest.

Le esclusioni permanenti sono tracciate nel repository della piattaforma (docs/SecurityExclusions.md): credenziali SuperAdmin da seed (X-01), Origin come difesa in profondità solo per token API (X-02), MFA/step-up differiti (X-03), alerting a livello SIEM (X-04), SDK social senza SRI (X-05), Flo.STRAPI fuori perimetro (X-06) e nginx non usato in produzione (X-07). Un finding che ricade in una di queste voci è citato come escluso, non riaperto silenziosamente.

Regole operative​

  • Mantieni aggiornate le checklist Pre-deploy/Post-deploy di ReleaseNotes.md: sono il runbook di rilascio (vedi Processo di Rilascio).
  • Non deployare mai aggirando il preflight risorse, e non usare mai --force senza autorizzazione esplicita per operazione.
  • Ruota i segreti su base pianificata e subito dopo ogni sospetta esposizione; flo secrets rotate accoda nuovi salt audit senza invalidare gli hash precedenti.
  • Completa un disarmo DR totale prima della manutenzione tenant o di un deploy MON: le guardie lease falliscono in modo chiuso e bloccano le scritture senza autorità valida. Vedi Failover e Disaster Recovery.
  • Monitora le superfici che veicolano segnali di sicurezza: eventi auth, pista audit, log applicativi e avvisi di flotta (Monitoraggio, Control Plane).
  • Non consolidare mai segreti o token. Una credenziale consolidata è un finding di sicurezza, non un dettaglio di configurazione.