rustup
rustup copied to clipboard
Force strong TLS 1.2 cipher suites in download/src/lib.rs because servers offer weak cipher suites
Describe the problem you are trying to solve
rustup-init.sh was recently updated to force strong TLS 1.2-1.3 cipher suites for downloading files (if supported by local tools). However, rustup itself isn't doing the same.
Schannel in Windows 7, 8, and 8.1 doesn't support the two strong cipher suites offered by rust servers (as of April 23, 2020), so this request is limited in scope to curl-backend + OpenSSL.
Describe the solution you'd like
~~Use the same strong TLS 1.2-1.3 cipher suites as rustup-init.sh (if supported by OpenSSL) when rustup is using curl-backend + OpenSSL.~~
One way is to configure reqwest to use rustls instead of native-tls.
rustls only supports 9 cipher suites and they're the same 9 we want enabled.
/// A list of all the cipher suites supported by rustls.
pub static ALL_CIPHERSUITES: [&SupportedCipherSuite; 9] =
[// TLS1.3 suites
&TLS13_CHACHA20_POLY1305_SHA256,
&TLS13_AES_256_GCM_SHA384,
&TLS13_AES_128_GCM_SHA256,
// TLS1.2 suites
&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
&TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
&TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
&TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
&TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
&TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256];
Author of reqwest says,
If you wish to try this out progressively, you can enable both default-tls and rustls-tls, and maybe check a config or env var to call either .use_default_tls() or .use_rustls_tls().
Thanks @kinnison and @seanmonstar for helpful feedback and suggestions.
Notes
-
Schannel TLS cipher suites in WIndows 8.1
https://docs.microsoft.com/en-us/windows/win32/secauthn/tls-cipher-suites-in-windows-8-1 -
I don't know how much fuzz testing is/was done for ring, rustls, and reqwest.
-
ringis in https://github.com/google/oss-fuzz/tree/master/projects -
rustlssecurity audit getting funded (stay tuned, maybe news "few months" from Feb 2020) https://github.com/ctz/rustls/issues/189 -
https://github.com/ctz/rustls-native-certs and https://github.com/ctz/webpki-roots and mkcert.org
-
#568 (old issue about supporting
rustlsas an option in rustup)
We are migrating away from the cURL binding toward reqwest as our only fetcher. We've defaulted to that for a while and eventually I'm going to drop cURL entirely. As such you probably need to investigate how we might be able to configure reqwest appropriately. This may need work on reqwest or hyper or some TLS bindings as well.
That seems reasonable.
However, reqwest is using Schannel on Windows. So Windows 7, 8.0 and 8.1 will connect to cargo.io and other rust-lang servers using only weak cipher suites because Schannel doesn't have required strong TLS 1.2 cipher suites until Windows 10. And Microsoft won't sunset Windows 8-8.1 until 2023.
Also, Active Directory policies can disable specific Schannel cipher suites without users knowing, which can create support issues for rustup and cargo.
I don't know if I'm the best person to ask @seanmonstar for security-related changes to reqwest. You have more gravitas and contacts in the rust community to make such a request.
Is there anyone assigned to be the official Rust security lead? In hindsight, Ken Thompson's hack showed the world in 1984 that compiler updates over the internet today might be a high value target.
I can't comment much on schannel. As an additional option, reqwest can be configured to use rustls (and disable native-tls), which I'd recommend over OpenSSL.
Thanks, I updated the issue based on helpful feedback from both of you.
The only 9 cipher suites supported by rustls are the same 9 we want enabled. :+1:
Okay, so two things - one we need to configure rustup to use rustls rather than native-tls in the reqwest dependency, and then second we need to get further into deprecating our use of cURL or even removing it?
@x448 Do you want to check if we're already using rustls and if not, cook up a PR to make it so?
I'd note that we need to be certain that things like the SSL CA certificate bundles etc which tend to be platform specific and configured by openssl will need to be verified as still working under rustls.
~~@seanmonstar, would you need to add rustls-native-certs as an option in reqwest before we can use it in rustup?~~
@kinnison I'm not seeing rustls being used (currently) by rustup. I think reqwest uses native-tls by default.
There's no clear-cut winner between webpki-roots (bundled root certs) and rustls-native-certs (OS provided root certs) which are both written by @ctz (author of rustls).
Although I prefer webpki-roots due to bad experience with Windows cert stores, it's "underlying data is MPL-licensed, and src/lib.rs is therefore a derived work." I don't know if this license issue matters to rustup, just pointing it out in case.
rustls-native-certs avoids the MPL license issue and will use OS-provided certs on MacOS, Windows, Linux and possibly more. Its README has a nice comparison vs webpki-roots.
rustls-native-certs is fairly new (Nov 2019 first release) and has almost 40 .toml files on GitHub that use it. By comparison, webpki-roots is in ~350 .toml files.
Maybe we should consider our own webpki-rust-root crate because rustup isn't a browser and will only connect to rust-lang controlled domains hosted by Amazon CloudFront. It can embed just the required/anticipated root certs like "Amazon Root CA 1", etc.. This would bypass the license issue and reduce needlessly trusted root certs.
If some unlucky users have employers that want to decrypt HTTPS traffic to gmail.com, etc. we can use native certs to be compatible with MITM decryption appliances. A 2nd rustup binary or command line option would be a "red pill" for some rust programmers compared to silent fallback.
FWIW, Windows cert store can get messy even without snooping employers, e.g. Dell's eDellRoot happened after Lenovo's Superfish: https://www.kb.cert.org/vuls/id/925497/
I wouldn't want to not be using the native certificate bundles. It's essential for permitting corporate situations where they MITM SSL etc.
We can have reqwest always use hyper-rustls which it already supports. And hyper-rustls uses rustls-native-certs by default since Nov 23, 2019.
This would give us the desired cipher suites without having to detect their support & specify them on various platforms and it would also use native certificate bundles.
I'm new to rust, so I'm not yet confident of my understanding of .toml files for rustup and reqwest.
If you wish to try this out progressively, you can enable both default-tls and rustls-tls, and maybe check a config or env var to call either .use_default_tls() or .use_rustls_tls().
I don't know how much fuzz testing is/was done for ring, rustls, and reqwest.
Merely feeding real-world data to ring has already revealed issues, so I do not expect it to hold up particularly well under fuzz testing. However, this is irrelevant to rustup unless ring has extensive use of unsafe code. The worst issues code detectable via fuzzing in safe code are panics, infinite loops or OOMs, and I don't think those are critical for rustup use cases.
https://github.com/trailofbits/siderophile/ may help you identify interesting targets for fuzzing that reach the largest amount of unsafe code, although I'm not sure how well it would work for an FFI-heavy crate such as ring.
I believe ring has quite a bit of unsafe code. I don't mind using reqwest with the OpenSSL backend so long as we can configure its cipher suites appropriately. Is that perhaps an easier thing to do ?
(The rustls/webpki/ring audit is starting next week, should take about 2 weeks.)
Third-party security audit of ring, webpki, and rustls:
- Nice summary by the author of
rustlsis at https://jbp.io/2020/06/14/rustls-audit.html - The report is at https://github.com/ctz/rustls/blob/master/audit/TLS-01-report.pdf
I was looking at the Cargo manifests for rustup and the download crate and found it pretty confusing that there seem to be like three download backends all enabled by default. Why is that?
@djc There's two backends, one with two options for TLS provider, because we've still not managed to bottom the problem which means reqwest wasn't working on armel on snapcraft, and we're not certain yet about the TLS provider change, so while we have a default, we're providing options for testing.
What's the current outlook on this?