Skip to content
Torna al blog
Sicurezza

Sicurezza Web online: hashing, validazione e autenticazione

Sicurezza web essenziale: bcrypt vs Argon2, prevenzione XSS e SQL injection, best practice JWT, header CSP e MFA con esempi di codice JS online.

12 min di lettura

Best practice di sicurezza per sviluppatori web

La sicurezza web non è opzionale. Con minacce informatiche in aumento, gli sviluppatori devono integrare la sicurezza in ogni livello delle loro applicazioni. Questa guida copre le pratiche essenziali da implementare oggi.

Sicurezza delle password

Non memorizzare mai password in chiaro

Calcola sempre l’hash delle password usando algoritmi moderni come bcrypt, Argon2 o scrypt. Questi algoritmi sono progettati per essere lenti, rendendo gli attacchi di forza bruta non praticabili.

// Buono: usare bcrypt
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);

Confronto degli algoritmi di hashing

Non tutti gli algoritmi di hashing sono uguali. Scegliere quello giusto dipende dal tuo modello di minaccia e dal caso d’uso:

AlgoritmoDimensione outputVelocitàCaso d’usoStato di sicurezza
MD5128 bitMolto veloceChecksum, hash non legati alla sicurezzaCompromesso per la sicurezza
SHA-256256 bitVeloceIntegrità dati, firme digitaliSicuro
bcrypt184 bitLento (regolabile)Hashing passwordSicuro
Argon2ConfigurabileLento (regolabile)Hashing password (moderno)Raccomandato per nuovi progetti

bcrypt e Argon2 sono deliberatamente lenti — è una caratteristica, non un bug. Ogni operazione di hash richiede decine o centinaia di millisecondi, rendendo gli attacchi di forza bruta su larga scala economicamente non praticabili.

Capire l’entropia delle password

La forza delle password si può misurare matematicamente con l’entropia: entropia = log2(charset_size^length). Una password che usa lettere minuscole (26 caratteri) con 8 caratteri ha ~37.6 bit di entropia. Una password di 16 caratteri che mescola maiuscole, minuscole, cifre e simboli (95 caratteri) ha ~105 bit — esponenzialmente più difficile da craccare. Per questo la lunghezza conta più della complessità per la maggior parte degli utenti. Per un approfondimento sulla matematica dietro la forza delle password, vedi la nostra guida entropia delle password spiegata.

Usa un password manager

Raccomanda ai tuoi utenti di adottare un password manager. Le password scelte da umani tendono a seguire pattern prevedibili che gli attaccanti sfruttano con attacchi a dizionario. I password manager generano stringhe veramente casuali ed eliminano il riutilizzo delle password tra servizi — uno dei vettori più comuni per attacchi di credential stuffing.

Usa un numero sufficiente di salt round

I salt round determinano il costo computazionale. Più alto è più sicuro ma più lento. 10-12 round sono un buon equilibrio per la maggior parte delle applicazioni.

Validazione dell’input

Valida sia lato client sia lato server

La validazione lato client migliora la UX, ma la validazione lato server è essenziale per la sicurezza. Non fidarti mai dell’input del client.

Sanifica tutto l’input utente

Previeni gli attacchi di iniezione sanificando l’input:

  • Usa query parametrizzate per SQL
  • Esegui l’escape dell’output HTML per prevenire XSS
  • Valida rigorosamente i caricamenti di file

Esempi concreti di attacchi

Capire gli attacchi reali aiuta a difendersi. Considera un form di commenti che renderizza l’input utente direttamente in HTML. Un attaccante invia:

<script>alert('xss')</script>

Se l’applicazione lo renderizza senza escape, lo script viene eseguito nel browser di ogni visitatore — rubando cookie, reindirizzando utenti o iniettando keylogger. Il fix: codifica sempre l’output contestualmente. Usa librerie come DOMPurify per la sanificazione HTML.

L’SQL injection è altrettanto pericolosa. In un form di login, un attaccante inserisce come username:

' OR 1=1 --

Se la query è costruita con concatenazione di stringhe ("SELECT * FROM users WHERE username='" + input + "'") questo aggira completamente l’autenticazione. I -- commentano il resto della query. Il fix: usa sempre query parametrizzate (chiamate anche prepared statement). Ogni libreria di database principale le supporta:

// SBAGLIATO: concatenazione di stringhe
db.query(`SELECT * FROM users WHERE username='${input}'`);

// CORRETTO: query parametrizzata
db.query('SELECT * FROM users WHERE username = $1', [input]);

Content Security Policy (CSP)

Come difesa in profondità, distribuisci header Content Security Policy. CSP dice al browser quali sorgenti di contenuto sono affidabili, bloccando di fatto script inline e caricamento di risorse non autorizzate. Anche se nel tuo codice esiste una vulnerabilità XSS, una CSP rigorosa può impedire l’esecuzione dello script iniettato. Inizia con Content-Security-Policy: default-src 'self' e aggiungi gradualmente eccezioni secondo necessità.

Funzioni hash

Scegliere l’hash giusto

Casi d’uso diversi richiedono funzioni hash diverse:

Caso d’usoRaccomandato
Passwordbcrypt, Argon2
IntegritàSHA-256
ChecksumSHA-256, MD5 (non sicurezza)
Hashing veloceBLAKE3

Capire output e collisioni dell’hash

MD5 produce un hash a 128 bit (32 caratteri hex), mentre SHA-256 produce un hash a 256 bit (64 caratteri hex). Questa differenza conta: uno spazio di output più grande significa esponenzialmente più valori hash possibili, rendendo le collisioni molto meno probabili. Una collisione si verifica quando due input diversi producono lo stesso hash — un attaccante in grado di generare collisioni può falsificare firme digitali o manomettere dati verificati.

Le collisioni MD5 possono essere generate in pochi secondi su hardware moderno. SHA-256 rimane resistente alle collisioni senza attacchi pratici noti. Per questo è critico scegliere l’algoritmo giusto per il contesto giusto:

  • Checksum e deduplicazione: MD5 è accettabile quando la sicurezza non è una preoccupazione
  • Integrità dei dati e firme: SHA-256 fornisce forte resistenza alle collisioni
  • Memorizzazione delle password: bcrypt o Argon2, che aggiungono salt e lentezza deliberata

HMAC per l’autenticazione dei messaggi

Quando devi verificare sia integrità sia autenticità di un messaggio, usa HMAC (Hash-based Message Authentication Code). HMAC combina una funzione hash con una chiave segreta, garantendo che solo le parti che conoscono la chiave possano generare o verificare il tag. È essenziale per autenticazione API, verifica di webhook e generazione sicura di token.

Non usare mai MD5 o SHA-1 per la sicurezza

MD5 e SHA-1 sono compromessi per scopi di sicurezza. Usa SHA-256 o SHA-3 per l’hashing crittografico.

HTTPS ovunque

Cosa fa effettivamente TLS

TLS (Transport Layer Security) fornisce tre protezioni critiche: crittografia in transito (impedisce l’intercettazione), autenticazione del server (dimostra che stai parlando con il server reale, non con un impostore) e integrità dei dati (rileva qualsiasi manomissione durante la trasmissione). Senza TLS, ogni dato tra i tuoi utenti e il tuo server — password, token, informazioni personali — viaggia in chiaro.

Usa sempre TLS

  • Ottieni certificati da CA affidabili (Let’s Encrypt è gratuito e completamente automatizzato)
  • Reindirizza HTTP a HTTPS
  • Usa header HSTS
  • Tieni aggiornate le versioni TLS

HSTS e contenuto misto

Gli header HTTP Strict Transport Security (HSTS) dicono ai browser di connettersi solo via HTTPS, anche se l’utente digita http://. Imposta Strict-Transport-Security: max-age=31536000; includeSubDomains per applicarlo per un anno intero su tutti i sottodomini. Questo previene gli attacchi di SSL stripping in cui un attaccante declassa una connessione a HTTP.

Attenzione agli avvisi di contenuto misto: se la tua pagina HTTPS carica immagini, script o fogli di stile via HTTP, i browser li bloccheranno o avviseranno. Verifica le tue pagine per URL http:// cablati e usa percorsi protocol-relative o forza HTTPS per tutte le risorse.

Autenticazione

Implementa il rate limiting

Previeni attacchi di forza bruta con il rate limiting:

  • Limita i tentativi di login per IP
  • Aggiungi ritardi dopo i tentativi falliti
  • Usa CAPTCHA per attività sospette

Basi dell’autenticazione JWT

I JSON Web Token (JWT) forniscono un meccanismo di autenticazione stateless strutturato come header.payload.signature. Il server firma il token con una chiave segreta, e i client lo includono nelle richieste successive. Poiché il token contiene i claim dell’utente, il server non deve cercare lo stato di sessione a ogni richiesta — il che rende i JWT adatti a sistemi distribuiti e microservizi.

Imposta sempre tempi di scadenza brevi sui token di accesso (es. 15 minuti) e usa refresh token per ottenere nuovi token di accesso. Memorizza i refresh token in modo sicuro (cookie httpOnly, non localStorage) e implementa la rotazione dei token in modo che ogni refresh token possa essere usato una sola volta.

Autenticazione a più fattori (MFA)

L’MFA non è più opzionale per qualsiasi applicazione seria. Richiedere un secondo fattore — codici TOTP (Google Authenticator), chiavi hardware (YubiKey) o notifiche push — riduce drasticamente l’impatto di password compromesse. Anche se un attaccante ottiene credenziali valide, non può autenticarsi senza il secondo fattore.

Prevenzione del session fixation

Gli attacchi di session fixation si verificano quando un attaccante imposta un session ID noto prima che l’utente si autentichi. Dopo il login, l’attaccante usa lo stesso session ID per dirottare la sessione autenticata. Previenilo rigenerando sempre il session ID dopo l’autenticazione riuscita e invalidando quello vecchio.

Usa una gestione sicura delle sessioni

  • Genera session ID crittograficamente casuali
  • Imposta i flag secure e httpOnly sui cookie
  • Implementa il timeout di sessione
  • Invalida le sessioni al logout

Checklist degli header di sicurezza

Distribuire i giusti header di risposta HTTP è uno dei modi più efficaci e a basso sforzo per rafforzare la tua applicazione. Ecco una tabella di riferimento rapida degli header di sicurezza essenziali:

HeaderScopoValore esempio
Content-Security-PolicyPrevenire XSS e iniezione di datidefault-src 'self'
Strict-Transport-SecurityForzare connessioni HTTPSmax-age=31536000; includeSubDomains
X-Content-Type-OptionsPrevenire MIME type sniffingnosniff
X-Frame-OptionsPrevenire clickjackingDENY
Referrer-PolicyControllare le informazioni di referrerstrict-origin-when-cross-origin

Questi header possono essere impostati a livello di web server (Nginx, Apache), a livello CDN/edge (Cloudflare, Vercel), o all’interno del framework della tua applicazione. Verifica i tuoi header con strumenti come securityheaders.com. Punta a una valutazione A+ — la maggior parte di questi header è una singola riga di configurazione e non costa nulla distribuirli.

Usare i nostri strumenti di sicurezza

Esplora i nostri strumenti di sicurezza per aiutarti nello sviluppo:

Per una panoramica più ampia su come gli strumenti di codifica, hashing e conversione si inseriscono nel tuo flusso di sviluppo, vedi la nostra Guida agli Strumenti Essenziali per Sviluppatori.

Domande frequenti

Qual è la vulnerabilità di sicurezza web più comune?

Cross-Site Scripting (XSS) rimane la vulnerabilità web più diffusa secondo OWASP. Si verifica quando le applicazioni includono dati non affidabili nelle pagine web senza una validazione adeguata. Previeni XSS sanificando tutto l’input utente, usando header Content Security Policy e codificando l’output in base al contesto (HTML, JavaScript, URL o CSS).

MD5 è ancora sicuro per l’hashing delle password?

No — MD5 non dovrebbe mai essere usato per l’hashing delle password. È computazionalmente veloce, il che lo rende vulnerabile ad attacchi di forza bruta e rainbow table. Le GPU moderne possono calcolare miliardi di hash MD5 al secondo. Usa invece bcrypt, scrypt o Argon2, che sono deliberatamente lenti e includono salt integrato per resistere agli attacchi.

Quanto dovrebbe essere lunga una password sicura nel 2026?

Si raccomanda un minimo di 12 caratteri, ma 16+ caratteri forniscono una protezione significativamente più forte. La lunghezza conta più della complessità — una passphrase di 20 caratteri come “correct-horse-battery-staple” è più forte di una password breve e complessa come “P@ss1!”. Abilita l’autenticazione a più fattori (MFA) indipendentemente dalla lunghezza della password per gli account critici.

Qual è la differenza tra crittografia e hashing?

La crittografia è reversibile — puoi decrittare i dati alla loro forma originale usando una chiave. L’hashing è a senso unico — non puoi recuperare i dati originali da un hash. Usa la crittografia per dati che devi recuperare (come dati utente memorizzati), e l’hashing per dati che devi solo verificare (come password e checksum).

Dovrei implementare il mio sistema di autenticazione?

No — costruire l’autenticazione da zero è rischioso e soggetto a errori. Usa framework e servizi collaudati come Auth0, Firebase Auth o Supabase Auth. Questi gestiscono hashing delle password, gestione delle sessioni, rotazione dei token, MFA e protezione dalla forza bruta. Concentra il tuo tempo di sviluppo sulle funzionalità uniche della tua applicazione.

Conclusione

La sicurezza è un processo continuo, non un’attività una tantum. Resta aggiornato sulle ultime vulnerabilità, fai audit regolari del tuo codice e segui il principio del minimo privilegio. I tuoi utenti si fidano di te con i loro dati - onora quella fiducia con pratiche di sicurezza robuste.

Articoli correlati

Vedi tutti gli articoli