Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unconstrained session cache growth in TLSv1.3 (3.1/3.0) #24044

Closed
19 changes: 19 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ OpenSSL 3.1

### Changes between 3.1.5 and 3.1.6 [xx XXX xxxx]

* Fixed an issue where some non-default TLS server configurations can cause
unbounded memory growth when processing TLSv1.3 sessions. An attacker may
exploit certain server configurations to trigger unbounded memory growth that
would lead to a Denial of Service

This problem can occur in TLSv1.3 if the non-default SSL_OP_NO_TICKET option
is being used (but not if early_data is also configured and the default
anti-replay protection is in use). In this case, under certain conditions,
the session cache can get into an incorrect state and it will fail to flush
properly as it fills. The session cache will continue to grow in an unbounded
manner. A malicious client could deliberately create the scenario for this
failure to force a Denial of Service. It may also happen by accident in
normal operation.

([CVE-2024-2511])

*Matt Caswell*

* New atexit configuration switch, which controls whether the OPENSSL_cleanup
is registered when libcrypto is unloaded. This can be used on platforms
where using atexit() from shared libraries causes crashes on exit.
Expand Down Expand Up @@ -19956,6 +19974,7 @@ ndif

<!-- Links -->

[CVE-2024-2511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-2511
[CVE-2024-0727]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-0727
[CVE-2023-6237]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6237
[CVE-2023-6129]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6129
Expand Down
4 changes: 3 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ OpenSSL 3.1

### Major changes between OpenSSL 3.1.5 and OpenSSL 3.1.6 [under development]

* none
* Fixed unbounded memory growth with session handling in TLSv1.3
([CVE-2024-2511])

### Major changes between OpenSSL 3.1.4 and OpenSSL 3.1.5 [30 Jan 2024]

Expand Down Expand Up @@ -1490,6 +1491,7 @@ OpenSSL 0.9.x

<!-- Links -->

[CVE-2024-2511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-2511
[CVE-2024-0727]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-0727
[CVE-2023-6237]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6237
[CVE-2023-6129]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6129
Expand Down
5 changes: 3 additions & 2 deletions ssl/ssl_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -3737,9 +3737,10 @@ void ssl_update_cache(SSL *s, int mode)

/*
* If the session_id_length is 0, we are not supposed to cache it, and it
* would be rather hard to do anyway :-)
* would be rather hard to do anyway :-). Also if the session has already
* been marked as not_resumable we should not cache it for later reuse.
*/
if (s->session->session_id_length == 0)
if (s->session->session_id_length == 0 || s->session->not_resumable)
return;

/*
Expand Down
34 changes: 28 additions & 6 deletions ssl/ssl_sess.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,11 @@ SSL_SESSION *SSL_SESSION_new(void)
return ss;
}

SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src)
{
return ssl_session_dup(src, 1);
}

/*
* Create a new SSL_SESSION and duplicate the contents of |src| into it. If
* ticket == 0 then no ticket information is duplicated, otherwise it is.
*/
SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
static SSL_SESSION *ssl_session_dup_intern(const SSL_SESSION *src, int ticket)
{
SSL_SESSION *dest;

Expand Down Expand Up @@ -287,6 +282,27 @@ SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
return NULL;
}

SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src)
{
return ssl_session_dup_intern(src, 1);
}

/*
* Used internally when duplicating a session which might be already shared.
* We will have resumed the original session. Subsequently we might have marked
* it as non-resumable (e.g. in another thread) - but this copy should be ok to
* resume from.
*/
SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
{
SSL_SESSION *sess = ssl_session_dup_intern(src, ticket);

if (sess != NULL)
sess->not_resumable = 0;

return sess;
}

const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
{
if (len)
Expand Down Expand Up @@ -517,6 +533,12 @@ SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, &copy);

if (ret != NULL) {
if (ret->not_resumable) {
/* If its not resumable then ignore this session */
if (!copy)
SSL_SESSION_free(ret);
return NULL;
}
ssl_tsan_counter(s->session_ctx,
&s->session_ctx->stats.sess_cb_hit);

Expand Down
5 changes: 2 additions & 3 deletions ssl/statem/statem_srvr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2338,9 +2338,8 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
* so the following won't overwrite an ID that we're supposed
* to send back.
*/
if (s->session->not_resumable ||
(!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
&& !s->hit))
if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
&& !s->hit)
s->session->session_id_length = 0;

if (usetls13) {
Expand Down