Cos'e'#
TLS (Transport Layer Security) e' il protocollo che cifra le connessioni di rete. Risolve tre problemi fondamentali in sequenza: verificare l'identita' del server, scambiare una chiave di sessione in modo sicuro, e cifrare tutto il traffico dati con quella chiave. SSL e' il predecessore deprecato — il nome sopravvive nel linguaggio comune e nel nome openssl, ma da usare TLS 1.2 o 1.3.

Protocollo che cifra le connessioni di rete usando un modello ibrido: crittografia asimmetrica per negoziare le chiavi (handshake), simmetrica AES per cifrare i dati.
TL;DR#
TLS risolve tre problemi in sequenza:
- Identita' del server: il certificato X.509 del server e' firmato da una CA fidata. Il browser verifica la catena localmente contro il trust store del sistema operativo.
- Key exchange sicuro: con ECDHE entrambi i lati derivano la stessa session key senza trasmetterla sulla rete. La chiave nasce nei due sistemi separatamente — non viaggia mai.
- Cifratura bulk: da quel momento tutto il traffico viaggia cifrato con AES. Veloce, hardware-accelerated, a ogni pacchetto.
L'handshake e' la parte costosa (asimmetrica, pochi millisecondi, fatta una volta per sessione). I dati viaggiano con AES (simmetrico, microsecondi, ogni pacchetto). TLS 1.3 rende questo schema obbligatorio e garantisce PFS per ogni sessione senza eccezioni.
Versioni Storiche#
La storia di SSL/TLS e' una sequenza di vulnerabilita' scoperte e versioni deprecate. Conoscere quale versione ha quale vulnerabilita' e' richiesto sia per l'esame sia per configurare correttamente un server.
SSL 1.0 → 1994, mai rilasciato
SSL 2.0 → 1995, subito bucato
SSL 3.0 → 1996, usato per anni — vulnerabile a POODLE (2015)
TLS 1.0 → 1999, vulnerabile a BEAST
TLS 1.1 → 2006, deprecated RFC 8996 (2021)
TLS 1.2 → 2008, ancora in uso — PFS opzionale (dipende dalla cipher suite)
TLS 1.3 → 2018, quello attuale — ECDHE obbligatorio, PFS sempre attivoSSL e' morto nel 2015. Quando dici "certificato SSL" intendi TLS. Il nome e' rimasto nel linguaggio comune — e nel nome openssl.
Modello Ibrido#
Il cuore di TLS e' l'uso combinato di crittografia asimmetrica e simmetrica. La asimmetrica risolve il problema della distribuzione delle chiavi (nessun canale sicuro necessario), ma e' troppo lenta per i dati. La simmetrica e' velocissima ma richiede una chiave condivisa in anticipo. TLS le usa in sequenza: asimmetrica per consegnare la chiave, simmetrica per i dati.
graph LR
CH["ClientHello
cipher suites"]
SH["ServerHello
+ certificato"]
KE["ECDHE
parametri pubblici"]
SK["Session Key
derivata localmente"]
AES["AES-256-GCM
bulk data"]
VEL["Veloce
hardware accel."]
subgraph HANDSHAKE["HANDSHAKE — asimmetrico, una volta sola"]
CH
SH
KE
SK
end
subgraph DATI["DATI — simmetrico, ogni pacchetto"]
AES
VEL
end
CH --> SH
SH --> KE
KE --> SK
SK -->|usa la session key| AES
AES --- VEL
Lettura: L'handshake (sinistra) usa ECDHE asimmetrico per derivare la session key — operazione costosa, fatta una sola volta per sessione. Da quel punto tutti i dati (destra) viaggiano con AES simmetrico, velocissimo.
Dev parallel: Quando fai
$client->request('GET', 'https://api.service.com')in Symfony ohttps.get()in Node.js, la libreria TLS sottostante esegue automaticamente l'handshake ECDHE e deriva la session key. Tu non chiami maiopenssl_encrypt()esplicitamente per ogni request — TLS lo fa a livello di trasporto. Quando invece cifri dati a riposo (un file upload, un campo DB sensibile), usi AES direttamente conopenssl_encrypt()in PHP ocrypto.createCipheriv()in Node: e' la stessa logica della Fase 2, senza la Fase 1 perche' la chiave la gestisci tu. La distinzione data in transit (TLS) vs data at rest (AES diretto) mappa esattamente sui due livelli del modello ibrido.
Il TLS Handshake#
Il TLS handshake e' la fase di negoziazione iniziale che avviene subito dopo il three-way handshake TCP. Browser e server si accordano su algoritmi, il server si autentica con il suo certificato, derivano insieme la session key tramite ECDHE, poi inizia la cifratura dei dati. In TLS 1.3 l'intero handshake richiede un solo round trip (1 RTT).
sequenceDiagram
participant B as Browser
participant S as Server
B->>S: TCP SYN
S->>B: TCP SYN-ACK
B->>S: TCP ACK
B->>S: Client Hello — versioni TLS e algoritmi supportati
S->>B: Server Hello — algoritmo scelto + certificato
B->>B: Verifica catena certificato fino a Root CA
B->>S: Parametro pubblico DH (A = g^a)
S->>B: Parametro pubblico DH (B = g^b)
note over B,S: Entrambi derivano la stessa chiave simmetrica
note over B,S: Nessuno ha mai mandato la chiave sulla rete
B->>S: Dati cifrati con AES
S->>B: Risposta cifrata con AES
Lettura: TLS handshake completo partendo dal TCP. Prima il three-way handshake TCP (SYN, SYN-ACK, ACK) per stabilire la connessione. Poi il TLS: Client Hello con algoritmi supportati, Server Hello con algoritmo scelto e certificato. Browser verifica la catena CA localmente. Scambio parametri DH: entrambi derivano la stessa chiave simmetrica senza trasmetterla. Da quel punto i dati viaggiano cifrati con AES.
La cifratura inizia sul computer del client, prima che il pacchetto esca.
Browser di Ubuntu
│
│ 1. TCP handshake con il server (non cifrato)
│ 2. TLS handshake (negoziazione algoritmi, scambio chiavi)
│ 3. Derivazione chiave simmetrica — avviene localmente
│ 4. Dati cifrati con AES
│
▼
[pacchetto gia' cifrato] ──► Kali (MITM) ──► internet ──► serverQuello che Kali vede con il MITM ARP su traffico HTTPS:
IP 192.168.64.3 > 216.58.x.x: TCP [SYN]
IP 192.168.64.3 > 216.58.x.x: TLSv1.3 Client Hello
IP 216.58.x.x > 192.168.64.3: TLSv1.3 Server Hello, Certificate
IP 192.168.64.3 > 216.58.x.x: [dati cifrati]
IP 216.58.x.x > 192.168.64.3: [dati cifrati]Vedi che sta avvenendo una comunicazione HTTPS, con quale server, quanto traffico, quando — ma non il contenuto. I dati sono gia' cifrati quando lasciano il browser. Questo e' esattamente perche' HTTPS esiste: proteggere dal MITM di rete.
Perfect Forward Secrecy#
PFS (Perfect Forward Secrecy) garantisce che la compromissione della chiave privata del server oggi non permetta di decifrare il traffico registrato in passato. E' la distinzione operativa fondamentale tra TLS 1.2 con RSA key exchange e TLS 1.3 con ECDHE — e una delle ragioni piu' importanti per migrare a TLS 1.3.
La E in ECDHE sta per Ephemeral — effimero.
Sessione 1: chiavi a1, b1 → chiave simmetrica K1 → scartata
Sessione 2: chiavi a2, b2 → chiave simmetrica K2 → scartata
Sessione 3: chiavi a3, b3 → chiave simmetrica K3 → scartataTLS 1.2 vs TLS 1.3 — la differenza chiave per PFS:
| TLS 1.2 (RSA) | TLS 1.2 (ECDHE) | TLS 1.3 | |
|---|---|---|---|
| Key exchange | RSA statico | ECDHE efimero | ECDHE efimero (obbligatorio) |
| Session key trasmessa? | Si (cifrata) | No (derivata) | No (derivata) |
| PFS garantito? | No | Si | Si (sempre) |
| Rischio se priv key rubata | Traffico passato decifra | Solo identita' compromessa | Solo identita' compromessa |
Come riconosci PFS nell'output di openssl:
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
# "New" = chiavi generate ora, mai usate prima — PFS attivo
# Se vedessi:
Reused, TLSv1.3, ...
# "Reused" = chiavi riciclate — PFS non funzionaTLS 1.3 rende ECDHE obbligatorio — PFS non e' piu' una scelta, e' la default.
Post-Quantum Cryptography#
La crittografia post-quantum protegge da attacchi futuri di computer quantistici. X25519 (Diffie-Hellman su curva ellittica, usato in TLS 1.3) e' vulnerabile all'algoritmo di Shor su un computer quantistico sufficientemente potente. Lo schema ibrido X25519MLKEM768 protegge usando due algoritmi in parallelo: se uno viene rotto, l'altro tiene.
Output reale di google.com:
Negotiated TLS1.3 group: X25519MLKEM768X25519 → Diffie-Hellman su curva ellittica (protegge oggi)
MLKEM768 → algoritmo post-quantum su reticoli (protegge dal futuro)
X25519MLKEM768 → ibrido: se uno cede, l'altro tieneUn computer quantistico puo' rompere X25519. MLKEM768 resiste ai computer quantistici. Usandoli insieme il blast radius di una compromissione e' limitato.
La Catena CA#
La catena CA (Certificate Authority) e' la sequenza di firme digitali che collega il certificato di un sito a una Root CA preinstallata nel sistema operativo. Ogni livello e' firmato dal livello sopra — spezzare anche un solo anello invalida tutta la catena e blocca la connessione.

Output reale di openssl s_client -connect google.com:443:
depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R1 # Root CA
depth=1 C=US, O=Google Trust Services, CN=WR2 # Intermediate CA
depth=0 CN=*.google.com # Certificato del sito
Certificate chain:
0 s: CN=*.google.com i: WR2 # sito firmato da Intermediate
1 s: WR2 i: GTS Root R1 # Intermediate firmata da Root
2 s: GTS Root R1 i: GlobalSign # Root firmata da GlobalSignIl pattern: l'i (issuer) di ogni livello e' l's (subject) del livello sopra. E' una catena letterale — se un anello e' rotto, la verifica fallisce.
GlobalSign Root CA (preinstallata nel tuo OS)
└── GTS Root R1 (Intermediate — firmata da GlobalSign)
└── WR2 (Intermediate — firmata da Root R1)
└── *.google.com (firmata da WR2)Se il certificato e' scaduto o revocato:
- Il browser non va in HTTP — blocca la connessione
- L'utente vede il warning rosso
- Niente dati in chiaro — niente connessione
Wildcard vs Certificato Specifico#
La scelta tra certificato wildcard e certificati separati e' una decisione di sicurezza prima che di comodita'. Il wildcard riduce i costi operativi ma aumenta il blast radius in caso di compromissione della chiave privata.
# Wildcard — copre tutti i sottodomini di primo livello
CN=*.google.com
copre: mail.google.com, maps.google.com, drive.google.com
NON copre: google.com, sub.mail.google.com
# Certificato specifico
CN=github.com
copre: solo github.comPerche' GitHub preferisce certificati separati:
Wildcard compromesso:
chiave rubata → tutti i sottodomini esposti
Certificati separati:
chiave rubata → solo quel dominio esposto
api.github.com, gist.github.com → salviStesso principio dello sviluppo: blast radius minimo.
Confronto TLS vs SSH#
TLS e SSH risolvono lo stesso problema (identita' + canale cifrato + PFS) con implementazioni diverse. Il punto di divergenza piu' importante e' il modello di fiducia: CA gerarchica vs TOFU.
TLS SSH
Scambio chiavi X25519MLKEM768 curve25519-sha256
Firma server ECDSA / certificato ed25519 / known_hosts
Fiducia CA preinstallata nel OS TOFU — Trust On First Use
Cifratura dati AES-256-GCM chacha20-poly1305
PFS ECDHE effimero curve25519 effimero
Auth client certificato client password o challenge-response
Replay protection — challenge casuale per firmaStessa struttura concettuale, implementazione diversa. Il problema da risolvere e' identico: identita' + canale cifrato + PFS.
Certificato → risponde a: "chi sei?" Chiave simmetrica AES → risponde a: "come cifriamo?"
Scenario Reale Blue Team#
Un certificato in scadenza non e' solo un problema di UX — e' un alert operativo. Un certificato scaduto su un servizio interno invisibile dal browser puo' indicare un servizio abbandonato, una superficie di attacco fuori dal perimetro di gestione.
# Controlla scadenza su piu' domini
for domain in google.com github.com api.internal.company.com; do
echo -n "$domain: "
echo | openssl s_client -connect $domain:443 2>/dev/null \
| openssl x509 -noout -enddate
done
# Verifica cipher suite e PFS
openssl s_client -connect api.service.com:443 2>/dev/null \
| grep -E "New|Reused|Cipher|Protocol"
# New = PFS attivo; Reused = PFS non funziona
# Protocol: TLSv1.3 = ok; TLSv1.2 = controlla cipher suite
# Cipher: TLS_AES_256_GCM_SHA384 = TLS 1.3 con AEAD, idealeUn certificato valido non significa che il sito e' sicuro. Significa solo che la connessione e' cifrata. Un attaccante puo' avere un certificato valido (Let's Encrypt e' gratuito) per un sito di phishing — la verifica del dominio va fatta separatamente.
New vs Reused nell'output openssl e' il check rapido per verificare se PFS e' attivo su un servizio che stai ispezionando. Su TLS 1.3 sara' sempre New — il protocollo non permette altro.
Collegato a#
- crypto — categoria
- cryptography — teoria crittografica di base
- pki — infrastruttura a chiave pubblica, catena CA, CRL/OCSP, DigiNotar
- ssh-protocol — stesso schema concettuale, implementazione diversa
- openssl-s_client — tool per ispezionare TLS da terminale


