
Proof-of-concept che riproduce CVE-2026-8932, una falla di corrispondenza incompleta nella configurazione mTLS nel riutilizzo delle connessioni di libcurl, con un server lab locale e un PoC in C.
Proof-of-concept per la riproduzione di CVE-2026-8932, un problema di corrispondenza incompleta della configurazione mTLS nel riutilizzo delle connessioni di libcurl.
CVE-2026-8932 riguarda la logica di riutilizzo delle connessioni di libcurl quando la configurazione di mutual TLS (mTLS) cambia tra una richiesta e l'altra.
In condizioni vulnerabili, libcurl può riutilizzare una connessione TLS esistente anche se un'opzione di configurazione relativa a mTLS è cambiata e avrebbe dovuto impedire il riutilizzo di quella connessione.
Questa PoC dimostra il problema modificando la password della chiave privata tra due richieste, utilizzando lo stesso certificato client e la stessa chiave privata.
La prima richiesta utilizza la password corretta:
correct-password
La seconda richiesta utilizza intenzionalmente una password non valida:
WRONG-PASSWORD
Se libcurl riutilizza in modo errato la connessione TLS esistente, la seconda richiesta non richiede un altro handshake TLS. Di conseguenza, la password non valida della chiave privata non è mai necessaria per stabilire una nuova connessione TLS e la richiesta riesce.
Il PoC dimostra quindi la condizione di riutilizzo della connessione associata a CVE-2026-8932.
| Proprietà | Valore |
|---|---|
| CVE | CVE-2026-8932 |
| Componente | libcurl |
| Tipo di vulnerabilità | Corrispondenza incompleta della configurazione mTLS |
| CWE | CWE-305 — Authentication Bypass by Primary Weakness |
| Area interessata | Riutilizzo della connessione TLS |
| Protocollo | HTTPS / mTLS |
| Client | API libcurl |
| curl CLI | Non interessato |
| Ambito del PoC | Ambiente di laboratorio locale |
La vulnerabilità è un problema di corrispondenza logica/di configurazione, piuttosto che una tradizionale vulnerabilità di sicurezza della memoria come un buffer overflow o un use-after-free.
libcurl mantiene le informazioni sulla connessione e può riutilizzare una connessione esistente quando una richiesta successiva è considerata compatibile con la configurazione della connessione.
Per le connessioni TLS, la configurazione della connessione deve quindi essere confrontata con attenzione prima del riutilizzo.
L'implementazione vulnerabile non includeva tutti i campi rilevanti della configurazione mTLS nella logica di corrispondenza della connessione.
Tra le impostazioni interessate figurano:
cert_type
key
key_type
key_passwd
key_blob
L'impostazione importante utilizzata da questo PoC è:
key_passwd
Il PoC stabilisce una connessione TLS utilizzando una chiave privata client cifrata e la password corretta:
correct-password
Poi esegue un'altra richiesta utilizzando lo stesso certificato e la stessa chiave ma cambia la password in:
WRONG-PASSWORD
Un'implementazione vulnerabile della corrispondenza delle connessioni potrebbe comunque considerare riutilizzabile la connessione esistente.
Il test consiste in due richieste HTTP.
La prima richiesta stabilisce la connessione TLS:
URL:
https://server.test:8443/A
Client certificate:
client.crt
Private key:
client.key
Key password:
correct-password
La connessione TLS rimane persistente perché il server supporta HTTP keep-alive.
La seconda richiesta utilizza lo stesso certificato e la stessa chiave privata ma cambia la password della chiave:
URL:
https://server.test:8443/B
Client certificate:
client.crt
Private key:
client.key
Key password:
WRONG-PASSWORD
Se libcurl crea una nuova connessione TLS, il caricamento della chiave privata cifrata con la password errata dovrebbe fallire.
Tuttavia, se libcurl riutilizza erroneamente la connessione esistente, non è richiesto un nuovo handshake TLS.
La password non valida, quindi, non impedisce il successo della richiesta HTTP.
L'allestimento del laboratorio è composto da:
localhost
|
v
+---------------------+
| Python mTLS Server |
| 127.0.0.1:8443 |
+----------+----------+
|
| HTTPS / TLS 1.3
|
+--------+--------+
| |
/A /B
\ /
\ /
v v
Same TLS Connection
|
v
libcurl
PoC (C)
L'osservazione importante è che /A e /B devono arrivare sulla stessa connessione TLS.
CVE-2026-8932-PoC/
├── README.md
├── LICENSE
├── .gitignore
│
├── certs/
│ └── .gitkeep
│
├── poc/
│ └── poc.c
│
├── server/
│ └── server.py
│
└── docs/
├── CVE-2026-8932-POC.jpg
├── CVE-2026-8932-server-POC.jpg
├── poc-output.txt
└── server-output.txt
La directory certs/ è intenzionalmente mantenuta vuota nel repository. I certificati e le chiavi private dovrebbero essere generati localmente.
Il PoC è stato testato nel seguente ambiente:
OS:
Debian GNU/Linux 13 (trixie)
Architecture:
x86_64
libcurl:
8.14.1
OpenSSL:
3.5.7
GCC:
14.2.0
L'installazione vulnerabile di libcurl utilizzata per la riproduzione era:
libcurl/8.14.1
Verifica la versione installata:
curl --version
e:
pkg-config --modversion libcurl
mkdir -p ~/cve-2026-8932-lab/{certs,poc,server,docs}
cd ~/cve-2026-8932-lab
cd ~/cve-2026-8932-lab/certs
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes \
-key ca.key \
-sha256 \
-days 3650 \
-subj "/CN=CVE-2026-8932-CA" \
-out ca.crt
Genera la chiave privata del server:
openssl genrsa -out server.key 2048
Genera la CSR:
openssl req -new \
-key server.key \
-subj "/CN=server.test" \
-out server.csr
Crea le estensioni del certificato:
printf "subjectAltName=DNS:server.test\nextendedKeyUsage=serverAuth\n" \
> server.ext
Firma il certificato utilizzando la CA di test:
openssl x509 -req \
-in server.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-out server.crt \
-days 3650 \
-sha256 \
-extfile server.ext
Genera la chiave privata del client:
openssl genrsa -out client.key.tmp 2048
Genera la CSR:
openssl req -new \
-key client.key.tmp \
-subj "/CN=Client-A" \
-out client.csr
Convertire la chiave privata nel formato PKCS#8 crittografato:
openssl pkcs8 \
-topk8 \
-in client.key.tmp \
-out client.key \
-v2 aes-256-cbc \
-passout pass:correct-password
La chiave privata risultante è crittografata con:
correct-password
Crea le estensioni del certificato client:
printf "extendedKeyUsage=clientAuth\n" \
> client.ext
Firma il certificato client: