|
| 1 | +```toml |
| 2 | +[advisory] |
| 3 | +id = "RUSTSEC-0000-0000" |
| 4 | +package = "openssl" |
| 5 | +date = "2025-02-02" |
| 6 | +url = "https://github.com/sfackler/rust-openssl/security/advisories/GHSA-rpmj-rpgj-qmpm" |
| 7 | +references = ["https://github.com/sfackler/rust-openssl/pull/2360"] |
| 8 | +categories = ["memory-exposure"] |
| 9 | +keywords = ["ssl", "tls", "alpn"] |
| 10 | +aliases = ["GHSA-rpmj-rpgj-qmpm"] |
| 11 | + |
| 12 | +[affected.functions] |
| 13 | +"openssl::ssl::select_next_proto" = [">= 0.10.0, < 0.10.70"] |
| 14 | + |
| 15 | +[versions] |
| 16 | +patched = [">= 0.10.70"] |
| 17 | +``` |
| 18 | + |
| 19 | +# ssl::select_next_proto use after free |
| 20 | + |
| 21 | +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. |
| 22 | + |
| 23 | +`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. |
| 24 | + |
| 25 | +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: |
| 26 | + |
| 27 | +Not vulnerable - the server buffer has a `'static` lifetime: |
| 28 | +```rust |
| 29 | +builder.set_alpn_select_callback(|_, client_protos| { |
| 30 | + ssl::select_next_proto(b"\x02h2", client_protos).ok_or_else(AlpnError::NOACK) |
| 31 | +}); |
| 32 | +``` |
| 33 | + |
| 34 | +Not vulnerable - the server buffer outlives the handshake: |
| 35 | +```rust |
| 36 | +let server_protos = b"\x02h2".to_vec(); |
| 37 | +builder.set_alpn_select_callback(|_, client_protos| { |
| 38 | + ssl::select_next_proto(&server_protos, client_protos).ok_or_else(AlpnError::NOACK) |
| 39 | +}); |
| 40 | +``` |
| 41 | + |
| 42 | +Vulnerable - the server buffer is freed when the callback returns: |
| 43 | +```rust |
| 44 | +builder.set_alpn_select_callback(|_, client_protos| { |
| 45 | + let server_protos = b"\x02h2".to_vec(); |
| 46 | + ssl::select_next_proto(&server_protos, client_protos).ok_or_else(AlpnError::NOACK) |
| 47 | +}); |
| 48 | +``` |
0 commit comments