Torna al blog
  • sicurezza
  • autenticazione
  • web app

5 errori che rendono vulnerabile il login della tua web app

Session token in localStorage, controlli solo lato client, password come unica barriera, niente rate limiting, password già compromesse: cosa evitare e cosa fare al loro posto.

Di Alessio Ferraro8 min di lettura
Quash, la mascotte quokka di Hash42 Labs, con occhiali scuri e cappotto nero in uno scenario verde in stile Matrix, sotto il titolo 5 Login Mistakes Putting Your App at Risk
In questo articolo

La schermata di login è spesso la parte più semplice di un'applicazione, almeno a vederla.

Email. Password. Un pulsante.

Dietro quei tre elementi c'è però un sistema molto più ampio: autenticazione, sessioni, autorizzazioni, difesa dagli attacchi automatizzati e gestione delle credenziali. Un login che funziona perfettamente non è per forza un login sicuro.

In questa guida trovi 5 errori frequenti nell'implementazione del login di una web app e, per ognuno, cosa fare al suo posto.

01. Salvare i session token in localStorage

Dopo l'accesso, l'applicazione deve conservare qualcosa che le permetta di riconoscere l'utente nelle richieste successive. Una scelta che si vede spesso è salvare il token direttamente nel browser:

localStorage.setItem("token", accessToken);

È comodo da implementare, ma ha un costo.

Perché è rischioso

Tutto ciò che sta in localStorage è leggibile da qualsiasi codice JavaScript eseguito sulla stessa origine. Se nell'applicazione esiste una vulnerabilità Cross-Site Scripting (XSS), lo script dell'attaccante può leggere il token e inviarlo altrove.

Vulnerabilità XSS
  ↓
JavaScript dell'attaccante
  ↓
localStorage
  ↓
Session token
  ↓
Account compromesso

Un token di sessione non è un dato dell'interfaccia: è una credenziale. Chi lo ottiene può, a seconda di come è costruito il sistema, agire al posto dell'utente.

Cosa fare

Per le sessioni web tradizionali, la strada più comune è un cookie configurato con questi attributi:

  • HttpOnly: il JavaScript della pagina non può leggerlo.
  • Secure: viaggia solo su HTTPS.
  • SameSite: limita l'invio del cookie nelle richieste provenienti da altri siti.

HttpOnly non elimina il rischio XSS e non sostituisce la protezione CSRF: uno script malevolo può ancora fare richieste dalla pagina mentre l'utente è collegato. Impedisce però che la credenziale venga letta e portata via.

La regola da ricordare: tratta sempre i session token come credenziali sensibili.

02. Fidarsi dei controlli lato client

Prendi un'applicazione con un pannello di amministrazione. Il frontend potrebbe contenere qualcosa del genere:

if (user.role === "admin") {
  showAdminPanel();
}

Va benissimo per decidere cosa mostrare nell'interfaccia. Non basta per decidere cosa l'utente ha il diritto di fare.

Il frontend non è una barriera di sicurezza

Tutto ciò che arriva al browser è, per definizione, sotto il controllo dell'utente. Chi usa l'applicazione può:

  • modificare le richieste HTTP;
  • chiamare direttamente un endpoint;
  • alterare lo stato del frontend;
  • manipolare i dati salvati in locale;
  • ignorare del tutto l'interfaccia.

Nascondere un pulsante non protegge l'API che quel pulsante chiama.

CLIENT                     SERVER

user.role === "admin"      richiesta
  ↓                          ↓
mostra il pulsante         sessione valida?
                             ↓
                           utente autorizzato?
                             ↓
                           azione consentita

La vera barriera è il controllo a destra.

Autorizzazione sul server

Ogni operazione sensibile va autorizzata dal server. Una richiesta come:

DELETE /api/users/42

non deve andare a buon fine solo perché il frontend, di solito, mostra quel comando agli amministratori. Il server deve verificare da solo chi sta facendo la richiesta e quali permessi ha.

Il client gestisce l'esperienza. Il server fa rispettare le regole.

03. Affidarsi soltanto alla password

Una password può essere lunga e complessa ed essere comunque compromessa. Può finire in un data breach, essere riutilizzata su più servizi, essere rubata con il phishing o intercettata da un malware.

Per questo, quando il livello di rischio lo richiede, la password non dovrebbe essere l'unica barriera.

Autenticazione a più fattori

La Multi-Factor Authentication (MFA) aggiunge una seconda verifica:

Password
  +
Secondo fattore
  ↓
Accesso

Anche con la password in mano, l'attaccante deve superare un secondo controllo. Non tutti i fattori però si equivalgono: un codice via SMS resiste molto meno di un'app di autenticazione o di una chiave hardware.

Passkey e WebAuthn

Dove l'applicazione lo permette, passkey e WebAuthn sono il passo successivo. Si basano sulla crittografia a chiave pubblica: la chiave privata resta sul dispositivo dell'utente, il server conserva solo quella pubblica. Non esiste quindi un segreto condiviso da rubare dal database, e la firma è legata al dominio del sito, cosa che le rende molto resistenti al phishing.

Dispositivo (chiave privata)
  ↓
firma crittografica
  ↓
Server (chiave pubblica)
  ↓
verificato

La scelta tra password, MFA e passkey dipende dal prodotto e dai rischi che deve affrontare. Il principio resta lo stesso: non progettare l'autenticazione dando per scontato che la password non verrà mai compromessa.

04. Lasciare il login senza rate limiting

Un endpoint di login pubblico deve ricevere richieste da Internet. Il problema nasce quando le accetta senza alcun limite.

Una persona fa qualche tentativo. Uno script ne fa migliaia.

LOGIN
LOGIN
LOGIN
LOGIN
LOGIN
...

Senza protezione, un attaccante può automatizzare i tentativi: indovinare password, provare in massa credenziali rubate altrove (credential stuffing) o semplicemente sovraccaricare l'endpoint.

Con rate limiting e throttling

Il sistema controlla frequenza e comportamento delle richieste:

Richieste
  ↓
Limite di frequenza
  ↓
Entro il limite → login
Oltre il limite → rifiutata o rallentata

Quando si supera un limite, la risposta HTTP tipica è 429 Too Many Requests. Restituire un 429 però non basta. Una strategia seria combina più segnali: limiti per indirizzo IP e per account, attese crescenti dopo ogni errore, rilevamento di comportamenti anomali.

Attenzione anche all'eccesso opposto: un blocco troppo aggressivo diventa un modo facile per chiudere fuori gli utenti veri. Il rate limiting serve a regolare il traffico, non a sbarrare la porta.

05. Accettare password deboli o già compromesse

Per anni la sicurezza delle password è stata riassunta così:

1 lettera maiuscola
1 lettera minuscola
1 numero
1 simbolo

Il risultato è spesso qualcosa come P@ssw0rd!: rispetta tutte le regole ed è tra le prime password che un attaccante prova.

Il problema delle password compromesse

Circolano miliardi di credenziali provenienti da vecchi data breach. Se un utente sceglie una password già presente in quelle liste, accettarla significa accettare una credenziale che gli attaccanti conoscono già.

Per questo le linee guida attuali, come quelle del NIST, chiedono di confrontare le nuove password con elenchi di password compromesse e comuni. Il controllo si può fare senza inviare la password a servizi esterni: Pwned Passwords, per esempio, riceve solo i primi caratteri del suo hash.

Password
  ↓
Lunghezza minima
  ↓
Controllo su password compromesse
  ↓
Nota o comune → rifiutata
Altrimenti → accettata

Le stesse linee guida sconsigliano le regole di composizione obbligatoria e i cambi periodici forzati. Contano di più la lunghezza, il rifiuto delle password note e il permesso di usare frasi lunghe e i password manager.

La sicurezza del login è un sistema

Non esiste un unico interruttore chiamato "login sicuro". Puoi avere la MFA e gestire male le sessioni. Puoi avere password eccellenti e un endpoint senza difese contro gli attacchi automatizzati. Puoi avere un'interfaccia che nasconde ogni funzione di amministrazione e un'API che non controlla i permessi.

Gestione delle sessioni
  ↓
Autorizzazione sul server
  ↓
Autenticazione
  ↓
Rate limiting
  ↓
Policy delle password
  ↓
Applicazione protetta

La sicurezza nasce dalla combinazione di questi livelli. Un sistema di autenticazione è forte quanto il suo anello più debole.

Checklist per sviluppatori

Prima di considerare finito il login di una web app, verifica almeno questi cinque punti:

  • I token e gli identificatori di sessione sono trattati come credenziali e non sono esposti inutilmente al JavaScript.
  • Le autorizzazioni sono verificate dal server, non solo dall'interfaccia.
  • Per gli account e le operazioni che lo richiedono è disponibile un secondo fattore o una passkey.
  • Gli endpoint di autenticazione hanno difese contro tentativi automatizzati e abusi.
  • Le password comuni o già compromesse vengono rifiutate.

Questa lista non rende sicura un'applicazione da sola, ma evita alcuni degli errori più ricorrenti.

La sicurezza comincia prima del deploy

La sicurezza non è qualcosa da aggiungere quando il prodotto è già online. Decisioni che sembrano piccole, come dove conservare una sessione o dove verificare un ruolo, fanno parte dell'architettura del prodotto.

Un buon login non si limita a far entrare l'utente. Stabilisce chi può entrare, cosa può fare, quanto ci si può fidare di ogni richiesta e cosa succede quando qualcuno prova ad abusare del sistema. È lì che il login smette di essere una schermata e diventa ingegneria del software.

Fonti

Condividi
Alessio Ferraro

Scritto da

Alessio Ferraro

Founder & Build Leader

meet al33xf

Hai un progetto in mente?

Hash42 Labs progetta e sviluppa web app, siti e prodotti digitali per attività e aziende, con la sicurezza pensata fin dal primo giorno. Gli stessi principi di questo articolo sono alla base di MANJI e Muni.