diff --git a/crates/openssl/RUSTSEC-0000-0000.md b/crates/openssl/RUSTSEC-0000-0000.md new file mode 100644 index 0000000000..1a9abdb581 --- /dev/null +++ b/crates/openssl/RUSTSEC-0000-0000.md @@ -0,0 +1,48 @@ +```toml +[advisory] +id = "RUSTSEC-0000-0000" +package = "openssl" +date = "2025-02-02" +url = "https://github.com/sfackler/rust-openssl/security/advisories/GHSA-rpmj-rpgj-qmpm" +references = ["https://github.com/sfackler/rust-openssl/pull/2360"] +categories = ["memory-exposure"] +keywords = ["ssl", "tls", "alpn"] +aliases = ["GHSA-rpmj-rpgj-qmpm"] + +[affected.functions] +"openssl::ssl::select_next_proto" = [">= 0.10.0, < 0.10.70"] + +[versions] +patched = [">= 0.10.70"] +``` + +# ssl::select_next_proto use after free + +In `openssl` versions before `0.10.70`, `ssl::select_next_proto` can return a slice pointing into the `server` argument's buffer but with a lifetime bound to the `client` argument. In situations where the `server` buffer's lifetime is shorter than the `client` buffer's, this can cause a use after free. This could cause the server to crash or to return arbitrary memory contents to the client. + +`openssl` 0.10.70 fixes the signature of `ssl::select_next_proto` to properly constrain the output buffer's lifetime to that of both input buffers. + +In standard usage of `ssl::select_next_proto` in the callback passed to `SslContextBuilder::set_alpn_select_callback`, code is only affected if the `server` buffer is constructed *within* the callback. For example: + +Not vulnerable - the server buffer has a `'static` lifetime: +```rust +builder.set_alpn_select_callback(|_, client_protos| { + ssl::select_next_proto(b"\x02h2", client_protos).ok_or_else(AlpnError::NOACK) +}); +``` + +Not vulnerable - the server buffer outlives the handshake: +```rust +let server_protos = b"\x02h2".to_vec(); +builder.set_alpn_select_callback(|_, client_protos| { + ssl::select_next_proto(&server_protos, client_protos).ok_or_else(AlpnError::NOACK) +}); +``` + +Vulnerable - the server buffer is freed when the callback returns: +```rust +builder.set_alpn_select_callback(|_, client_protos| { + let server_protos = b"\x02h2".to_vec(); + ssl::select_next_proto(&server_protos, client_protos).ok_or_else(AlpnError::NOACK) +}); +```