Confondere i mediatori malintenzionati con HTTPS e HTTP Strict Transport Security

Data la quantità di dati personali che scorre attraverso la grande serie di "tubi" che è internet, la crittografia non è qualcosa che possiamo o dobbiamo ignorare facilmente. I browser moderni offrono diversi meccanismi che puoi utilizzare per garantire la sicurezza dei dati degli utenti durante il transito: i cookie sicuri e Strict Transport Security sono due dei più importanti. Ti consentono di proteggere facilmente i tuoi utenti, eseguendo l'upgrade delle loro connessioni a HTTPS e garantendo che i dati degli utenti non vengano mai inviati in chiaro.

Perché dovrebbe interessarti? Considera quanto segue:

Inviare una pagina web tramite una connessione HTTP non criptata è più o meno come consegnare una busta non sigillata alla prima persona che vedi per strada e che sembra dirigersi verso l'ufficio postale. Se hai fortuna, potrebbe portarlo fino a destinazione o consegnarlo alla prima persona che vede in direzione giusta. La stessa cosa potrebbe fare la persona che ha ricevuto il messaggio e così via.

La maggior parte degli sconosciuti di questa catena estemporanea è affidabile e non darebbe mai un'occhiata alla tua lettera aperta o la modificherebbe. Tuttavia, più volte la lettera cambia proprietario, maggiore è il numero di persone con accesso completo alla lettera che stai inviando. Alla fine, è molto probabile che il destinatario previsto della lettera riceva qualcosa per posta, ma se si tratta della stessa cosa che hai consegnato inizialmente è una domanda aperta. Forse avresti dovuto sigillare la busta…

Intermediari

Per fortuna o per sfortuna, enormi aree di internet si basano sull'affidabilità di estranei. I server non sono collegati direttamente tra loro, ma trasmettono richieste e risposte da un router all'altro in un enorme gioco del telefono.

Puoi vedere questi hop in azione con traceroute. Il percorso dal mio computer a HTML5Rocks è simile al seguente:

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 hop non è male, davvero. Tuttavia, se invio richieste tramite HTTP, ciascuno di questi router intermedi ha accesso completo alle mie richieste e alle risposte dei server. Tutti i dati vengono trasferiti come testo non criptato e qualsiasi intermediario potrebbe agire come Man in the Middle, leggendo i miei dati o addirittura manipolandone il transito.

Peggio ancora, questo tipo di intercettazione è praticamente non rilevabile. Una risposta HTTP modificata con dolo sembra esattamente una risposta valida, in quanto non esiste un meccanismo che ti consenta di garantire che i dati ricevuti siano _esattamente_ i dati inviati. Se qualcuno decide di scombinare la mia connessione a internet per divertirsi, non ho molte opzioni.

È una linea sicura?

Il passaggio da HTTP non criptato a una connessione HTTPS protetta offre la migliore difesa contro i mediatori. Le connessioni HTTPS criptano l'intero canale da un capo all'altro prima che vengano inviati dati, impedendo ai computer tra te e la tua destinazione di leggere o modificare i dati in transito.

L'omnibox di Chrome fornisce molti dettagli sullo stato di una connessione.
L'omnibox di Chrome fornisce molti dettagli sullo stato di una connessione.

La sicurezza fornita da HTTPS si basa sul concetto di chiavi crittografiche pubbliche e private. Una discussione approfondita dei dettagli è (fortunatamente) ben oltre l'ambito di questo articolo, ma la premessa di base è abbastanza semplice: i dati criptati con una determinata chiave pubblica possono essere decriptati solo con la chiave privata corrispondente. Quando un browser avvia un'handshake HTTPS per creare un canale sicuro, il server fornisce un certificato che fornisce al browser tutte le informazioni necessarie per verificare la sua identità controllando che il server sia in possesso della chiave privata corretta. Da quel punto in poi, tutte le comunicazioni vengono criptate in modo da dimostrare che le richieste vengono inviate e le risposte ricevute dal server autenticato.

HTTPS, quindi, ti garantisce che stai parlando con il server che pensi di utilizzare e che nessun altro stia ascoltando o modificando i bit sulla rete. Questo tipo di crittografia è un prerequisito assoluto per la sicurezza sul web. Se al momento la tua applicazione non viene pubblicata tramite HTTPS, è vulnerabile agli attacchi. Correggi l'errore. Ars Technica ha una fantastica guida per ottenere e installare un certificato (senza costi) che ti consiglio di consultare per i dettagli tecnici. La configurazione varierà da fornitore a fornitore e da server a server, ma la procedura di richiesta del certificato è la stessa ovunque.

Sicuro di default

Dopo aver richiesto e installato un certificato, assicurati che gli utenti trarrebbero vantaggio dal tuo impegno: esegui la migrazione degli utenti esistenti alle connessioni HTTPS in modo trasparente tramite il magico reindirizzamento HTTP e assicurati che i cookie vengano inviati solo tramite connessioni sicure.

Da questa parte

Quando un utente visita http://example.com/, reindirizzalo a https://example.com/ inviando una risposta 301 Moved Permanently con un'intestazione Location appropriata:

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

Puoi configurare facilmente questo tipo di reindirizzamento in server come Apache o Nginx. Ad esempio, una configurazione Nginx che reindirizza da http://example.com/ a https://example.com/ è simile alla seguente:

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

I cookie ci consentono di offrire agli utenti un'esperienza di accesso senza problemi tramite il protocollo HTTP senza stato. I dati memorizzati nei cookie, incluse informazioni sensibili come gli ID sessione, vengono inviati con ogni richiesta, consentendo al server di capire a quale utente sta rispondendo al momento. Dopo aver verificato che gli utenti accedono al nostro sito tramite HTTPS, dobbiamo anche assicurarci che i dati sensibili memorizzati nei cookie vengano trasferiti solo tramite una connessione sicura e mai in chiaro.

L'impostazione di un cookie in genere prevede un'intestazione HTTP simile alla seguente:

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

Puoi chiedere al browser di limitare l'utilizzo del cookie alle sessioni sicure applicando una singola parola chiave:

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

I cookie impostati con la parola chiave secure non verranno mai inviati tramite HTTP.

Chiusura della finestra aperta

Il reindirizzamento trasparente a HTTPS significa che la maggior parte delle volte in cui gli utenti sono sul tuo sito utilizzeranno una connessione sicura. Tuttavia, lascia una piccola opportunità di attacco: la connessione HTTP iniziale è completamente aperta e vulnerabile allo stripping SSL e ad attacchi correlati. Poiché un malintenzionato ha accesso completo alla richiesta HTTP iniziale, può agire come proxy tra te e il server, mantenendoti su una connessione HTTP non sicura, indipendentemente dalle intenzioni del server.

Puoi ridurre il rischio di questa classe di attacchi chiedendo al browser di applicare HTTP Strict Transport Security (HSTS). L'invio dell'intestazione HTTP Strict-Transport-Security indica al browser di eseguire il reindirizzamento da HTTP ad HTTPS lato client, senza mai toccare la rete (questo è anche ottimo per le prestazioni; la richiesta migliore è quella che non devi fare):

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

I browser che supportano questo intestazione (attualmente Firefox, Chrome e Opera: caniuse fornisce i dettagli) anno annotato che questo sito specifico ha richiesto l'accesso solo tramite HTTPS, il che significa che, indipendentemente da come un utente accede al sito, lo visiterà tramite HTTPS. Anche se digita http://example.com/ nel browser, finirà su HTTPS senza mai effettuare una connessione HTTP. Ancora meglio, se il browser rileva un certificato non valido (che potrebbe tentare di rubare l'identità del tuo server), gli utenti non potranno continuare tramite HTTP. È tutto o niente, un'ottima soluzione.

Il browser scadrà lo stato HSTS del server dopo max-age secondi (circa un mese in questo esempio); imposta un valore ragionevolmente elevato.

Puoi anche assicurarti che tutti i sottodomini di un'origine siano protetti aggiungendo la direttiva includeSubDomains all'intestazione:

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Vai avanti, in sicurezza

HTTPS è l'unico modo per avere anche solo lontanamente la certezza che i dati inviati raggiungano il destinatario previsto intatti. Ti consigliamo di configurare connessioni sicure per i tuoi siti e le tue applicazioni oggi stesso. Si tratta di una procedura abbastanza semplice che ti aiuterà a mantenere al sicuro i dati dei tuoi clienti. Una volta creato un canale criptato, devi reindirizzare in modo trasparente gli utenti a questa connessione sicura, indipendentemente da come accedono al tuo sito, inviando una risposta HTTP 301. Poi, assicurati che le informazioni sensibili sulle sessioni di tutti gli utenti utilizzino soltanto questa connessione sicura aggiungendo la parola chiave secure quando imposti i cookie. Dopodiché, assicurati che i tuoi utenti non perdano mai accidentalmente il bus: proteggili garantendo che il browser agisca correttamente inviando un'intestazione Strict-Transport-Security.

La configurazione di HTTPS non richiede molto lavoro e offre enormi vantaggi per il tuo sito e i suoi utenti. Vale la pena.

Risorse

  • StartSSL offre certificati senza costi con verifica del dominio. Non c'è niente di meglio del senza costi. Naturalmente, è possibile passare a livelli di verifica superiori a un prezzo ragionevole.
  • Test del server SSL: dopo aver configurato HTTPS per i tuoi server, verifica di aver eseguito correttamente l'operazione eseguendo il test del server di SSL Labs. Riceverai un report dettagliato che ti mostrerà se tutto è a posto.
  • L'articolo recente di Ars Technica "Securing your Web Server with SSL/TLS" vale la pena di essere letto per avere qualche dettaglio in più sulle nozioni di base della configurazione di un server.
  • La specifica HTTP Strict Transport Security (RFC6797) vale la pena di essere letta per tutte le informazioni tecniche sull'intestazione Strict-Transport-Security che potresti volere.
  • Una volta che sai esattamente cosa stai facendo, un possibile passaggio successivo potrebbe essere comunicare che il tuo sito deve essere raggiungibile solo tramite un insieme specifico di certificati. L'IETF sta lavorando a un progetto che ti consentirebbe di fare proprio questo tramite l'intestazione Public-Key-Pins. È ancora presto, ma è un progetto interessante e vale la pena seguirlo.