Un IDS come Suricata o un WAF leggono il payload; ma con TLS 1.3 il payload è cifrato e anche il certificato del server non è più visibile. Il malware lo sa: usa HTTPS per C2 ed esfiltrazione, convinto di essere invisibile. La TLS inspection (o SSL bump) è la contromisura aziendale: un proxy si mette in mezzo, decifra, ispeziona e ricifra. È una vera attività di man-in-the-middle, autorizzata, e come tale ha costi e rischi che vanno progettati.
Perché conta
Senza inspection si può filtrare solo su IP, SNI e metadati (Zeek li sfrutta bene). Con inspection si vedono URL, header, file scaricati (antivirus, sandbox) e richieste DLP. Ma il proxy diventa un bersaglio di valore enorme: la sua CA, se rubata, permette di intercettare tutta l’azienda. Aggiungi il costo prestazionale: due handshake e due cifrature per ogni connessione. Con handshake ECDHE (vedi TLS deep dive) il costo è dominato dalle operazioni su curva ellittica; la capacità si stima come
$$N_{max} \approx \frac{C_{cpu}\cdot n_{core}}{t_{hs}+ B/,r_{aead}}$$
dove $t_{hs}$ è il tempo di handshake per connessione, $B$ i byte trasferiti e $r_{aead}$ il throughput AEAD per core.
Come funziona
Il client è configurato per fidarsi di una CA interna. Il proxy genera al volo un certificato per il sito richiesto, firmato da quella CA, e apre una seconda sessione TLS verso il server vero.
sequenceDiagram
participant C as Client
participant P as Proxy (CA interna)
participant S as Server
C->>P: CONNECT example.org:443
C->>P: ClientHello (SNI = example.org)
P->>S: ClientHello (peek)
S-->>P: ServerHello, Certificate
P->>P: genera cert example.org firmato dalla CA interna
P-->>C: ServerHello, cert forgiato
Note over C,P: Sessione TLS 1
P->>S: sessione TLS 2 (cert verificato dal proxy)
C->>P: GET /file (in chiaro nel proxy)
P->>S: GET /file
Squid decide per connessione tra tre azioni: peek (legge il ClientHello/ServerHello senza decidere), splice (tunnel opaco, nessuna decifrazione) e bump (intercetta). L’ordine corretto è peek al passo 1, poi splice o bump in base a SNI e categoria.
L’attacco
L’inspection ha anche un lato offensivo: è quello che fa mitmproxy in un pentest e che un malware con privilegi
locali fa installando una CA nel trust store. Su un host di test:
|
|
Senza --cacert il client rifiuta: curl: (60) SSL certificate problem: unable to get local issuer certificate.
È la prova che la fiducia nasce dalla CA, non dal proxy. I punti deboli di una inspection mal fatta sono tre: (1) la CA
con chiave non protetta e senza vincoli, (2) il proxy che accetta certificati server non validi e li “ripulisce” con il
suo cert valido, (3) il pinning applicativo (app mobili, client Git) che si rompe e spinge a spegnere le verifiche.
La difesa
La difesa è ridurre il raggio d’azione: CA dedicata con vincoli, chiave in HSM o almeno su file 0400, bump solo dove serve, splice per categorie sensibili (banking, sanità, privacy) e verifica rigorosa del certificato reale.
|
|
Le righe evidenziate: sslproxy_cert_error deny all impedisce di nascondere errori del server reale (certificato
scaduto, hostname errato); peek poi splice permette di decidere sull’SNI senza decifrare; bump all intercetta
il resto. La CA va creata con basicConstraints=CA:TRUE,pathlen:0 ed, se possibile, con nameConstraints (RFC 5280)
che la limitano ai domini di cui l’azienda risponde. Per i client rimangono:
- distribuzione della CA via GPO/MDM, mai installata a mano;
- policy interna e informativa ai dipendenti (obbligo legale in UE per il trattamento dei dati);
- log del proxy inviati al SIEM con hash della richiesta, non il contenuto;
- ECH rende il peek sull’SNI inefficace: serve decidere su IP/categoria o disattivare ECH via DNS interno.
Lab
Con un container Squid, un client Linux e un sito di test:
- Genera la CA e configura Squid con
ssl_bump bump all; installaca.crtnel client e scarica un file concurl. Quale issuer vedeopenssl s_client -connect example.org:443 -proxy 127.0.0.1:3128? - Aggiungi
ssl_bump spliceper.bank.example: cosa cambia nell’issuer per quel dominio? - Servi dal sito di test un certificato scaduto con
bump allesslproxy_cert_errorcommentata: cosa vede il client? E condeny all?
Soluzione
- L'issuer è
CN=Lab Interception CA: il certificato visto dal client è forgiato dal proxy. - Con splice il proxy non decifra e l'issuer torna quello reale (per esempio Let's Encrypt): nessuna ispezione, ma anche nessuna rottura di pinning.
- Con la direttiva commentata (o
allow all) il proxy accetta il certificato scaduto e il client lo vede valido: è la vulnerabilità tipica. Condeny allil client riceve una pagina di errore generata da Squid.
Conclusione
La TLS inspection restituisce visibilità, ma sposta la fiducia su una CA che va protetta come una chiave di dominio. Regole pratiche: bump selettivo, splice sulle categorie sensibili, verifica severa dei certificati reali, CA vincolata e monitorata. Dove possibile, preferisci mTLS e identità dei workload ai proxy intercettanti: meno magia, più fiducia esplicita.
Prossimo nella serie: Torna alla roadmap