Closed gstrauss closed 1 day ago
For DH parameters code review, I checked all servers which had .hbs configs containing {{#if output.usesDhe}}
. I downloaded the source code and checked the history to find supported versions.
lighttpd - no change; does the right things with the appropriate versions
apache - small changes to do the right things with appropriate versions postfix - small changes to do the right things with appropriate versions redis - small changes to do the right things with appropriate versions
coturn - no change; does not call SSL_CTX_set_dh_auto/SSL_set_dh_auto dovecot - no change; does not call SSL_CTX_set_dh_auto/SSL_set_dh_auto exim - no change; does not call SSL_CTX_set_dh_auto/SSL_set_dh_auto haproxy - no change; does not call SSL_CTX_set_dh_auto/SSL_set_dh_auto nginx - no change; does not call SSL_CTX_set_dh_auto/SSL_set_dh_auto postgresql - no change; does not call SSL_CTX_set_dh_auto/SSL_set_dh_auto proftpd - no change; does not call SSL_CTX_set_dh_auto/SSL_set_dh_auto squid - no change; does not call SSL_CTX_set_dh_auto/SSL_set_dh_auto
There are some apps, such as stunnel and postgresql, which use built-in 2048-bit pregenerated DH params, if none is otherwise configured. Some other servers many support DH params included in certificate PEM file. This PR does not review bit sizes of DH params as that is out of scope for this PR -- which is focused on upgrading the OpenSSL version supported by ssl-config-generator. Besides, best practices in modern configs no longer use DHE.
RFE: I would like to discussion renaming "Old" config to "Insecure", because that is what it is. It provides obscurity over clear-text, but is not considered "secure" by modern specifications. It fails all modern security standards and so the remaining value is compatibility with ancient devices and possibly historical verification of now-obsolete older security standards.
For TLSv1 and TLSv1.1 (also no longer considered secure), @SECLEVEL=0 in the cipher list should suffice. Another alternative would be suggesting modifications to /etc/ssl/openssl.cnf
or /etc/pki/tls/openssl.cnf
, but I think modifying the cipher string scopes SECLEVEL=0 to the app, which is better than suggesting lowering the OpenSSL library security for all apps on the system using openssl.
I will be addressing this gradually, mostly looking into some template options to avoid the repetition, TBD…
I would like to discussion renaming "Old" config to "Insecure", because that is what it is. It provides obscurity over clear-text, but is not considered "secure" by modern specifications.
That name is a term within the org: https://infosec.mozilla.org/guidelines/risk/scoring_and_other_levels.html#recommended-configuration-states
A lot of effort went (back in the day) to make this config usable, not having anything directly compromised etc., so it's still a nudge above "insecure" in the scoring (yellow, grade "D" to "D-"); basically anything moved out of old
in the past decade can be deemed insecure (red, grade "F") in comparison. I believe the rationale below the list still stands. (The issue is none of that is directly visible in the UI here, that is definitely a deficiency.)
Given the specs are due for update anyways, I can see some old
cleanup and demotions from intermediate
in the cards eventually… so no need to re-label it with catastrophic badges, it only needs to move the suites along gradually.
For TLSv1 and TLSv1.1 (also no longer considered secure), @SECLEVEL=0 in the cipher list should suffice.
There will be some servers that won't know how to support that (individual keys for ciphers instead of the cipher string; will need to look into the implementations), but happy to have old configs on 3+ only as a best effort, if documented as such…
Do we also want to map when a server doesn't support 3+? (Does it still happen today?)
This PR does not review bit sizes of DH params as that is out of scope for this PR
I'm actually comfortable with letting intermediate fail to apply on <80 bits — that's a reminder for the consumer they're not careful with the key size as instructed.
In the future, if we do consider renaming the profiles, I would like to propose including a date in the spec. Even if only a year, "modern-2020" is much more descriptive than the current almost 5-year old (!) "modern", which I do not consider modern.
For TLSv1 and TLSv1.1 (also no longer considered secure), @SECLEVEL=0 in the cipher list should suffice.
There will be some servers that won't know how to support that (individual keys for ciphers instead of the cipher string; will need to look into the implementations), but happy to have old configs on 3+ only as a best effort, if documented as such…
Most of the app templates join the cipher list with ':'. The ones that do not are awselb caddy go jetty traefik, so we'll have to look to see how they handle (or not) @SECLEVEL=0
. I was trying to avoid creating a new variable for @SECLEVEL=0 that had to be pasted onto the cipher list and have code added to each and every src/templates/partials/*.hbs
for addition to the cipher lists (where applicable).
Do we also want to map when a server doesn't support 3+? (Does it still happen today?)
Unlikely. All versions of OpenSSL earlier than openssl 3.0.0 are EOL and not supported by the OpenSSL Foundation, though paid Premium Support is still available from the OpenSSL Corporation for some older openssl versions.
This PR does not review bit sizes of DH params as that is out of scope for this PR
I'm actually comfortable with letting intermediate fail to apply on <80 bits — that's a reminder for the consumer they're not careful with the key size as instructed.
The default SECLEVEL=2
, and we should retain that. At SECLEVEL=1
, TLSv1 and TLSv1.1 are disabled, so if the Old config needs them, those who need it must use SECLEVEL=0
To address your review comment about apps that do not pass a ':'-separated cipher string to openssl, I pushed a change to avoid adding @SECLEVEL=0
to the cipher list for ['awselb','caddy','go','jetty','traefik']
. We'll need to add a comment in each of this .hbs files that @SECLEVEL=0
will need to be configured in openssl.cnf
unless there is a different way that these apps expose to configure the security level in their config files. (not done yet)
['awselb','caddy','go','jetty','traefik'] all are configured usesOpenssl: false
, so I removed that unnecessary check.
I also reconsidered and change the form['config'].value === 'old'
test to protocols.includes('TLSv1.1')
since SECLEVEL=0
is needed by OpenSSL 3 for TLSv1 and TLSv1.1 used by the Old configuration.
@janbrasna I think this is ready for commit. Please give this priority for re-review. Thanks!
I feel it would be negligent to unnecessarily delay recommending configs supporting OpenSSL 3.x. On the other hand, if there are are few bugs that turn up in specific apps for Old configuration -- which we want to discourage anyway due to low security -- then those are bugs and can be fixed.
I incorporated the changes in #257 and updated the Apache version here.
Ready for review again with the changes from #257. The last few pushes were whitespace cleanup.
I will also try to document what info should be added upstream, to the recommendation contents, as a rationale for the choices we're making to support OpenSSL 3. (I will add it to the #260 epic where I intend to track things even spanning the actual repos…)
I'm thinking about a review meeting to go through some of the things, TBD, I'll put together a list/backlog for that to see how much we have left that I'd like to discuss before confirming any decisions.
(I have more questions than actual time to even ask them — some of the issues are solving themselves over time, I'm not sure about Tomcat impact (if you can try to find out it won't trip over the seclevel in cipherstring as it does some own parsing before passing anything on…), will have more questions about the seclevel bit-strength threshold wrt our other output values than just the protocols etc. …)
What's mostly unknown to me are the os-level specifics that can differ for folks, e.g.:
"This may have more implications than just re-enabling TLSv1.0 and 1.1 (or rather: SHA1 and MD5 signature algorithms, used by these protocols) though, depending on the OpenSSL version. See man SSL_CTX_set_security_level(3) on the same machine." — https://github.com/mozilla/ssl-config-generator/issues/188#issuecomment-1534798621
Can you think of any wild differences among versions or distros/defaults?
I would love for this to be first released as "opt-in" — say by skipping the 3.x version in configs.js now, we can ask people to manually test 3.x configs by punching in the version (or via permalink), before settling on that as the new default for anyone and everyone. Mainly to verify we're still good on 1.1.1 not bringing any regressions to the existing logic, and giving it few weeks for feedback before flipping that switch. (If it is long overdue, long+14d overdue doesn't make much difference.)
I'm not sure about Tomcat impact
No impact. Tomcat is configured in src/js/config.js with usesOpenssl: false
and that is checked before adding SECLEVEL=0
"This may have more implications than just re-enabling TLSv1.0 and 1.1 ...
Can you think of any wild differences among versions or distros/defaults?
From a practical perspective, it does not matter since it is required to support TLSv1 and TLSv1.1, and if the Old config provides support for TLSv1 and TLSv1.1, then SECLEVEL=0
must be set if OpenSSL 3.x is used.
I would love for this to be first released as "opt-in" — say by skipping the 3.x version in configs.js now
Ok. I will push momentarily with that commit removed.
This PR does not review bit sizes of DH params as that is out of scope for this PR
I'm actually comfortable with letting intermediate fail to apply on <80 bits — that's a reminder for the consumer they're not careful with the key size as instructed.
The default
SECLEVEL=2
, and we should retain that. AtSECLEVEL=1
, TLSv1 and TLSv1.1 are disabled, so if the Old config needs them, those who need it must useSECLEVEL=0
Ah right, I meant <112 bits, sorry. That kinda enforces the RSA and DHE keys length 2048b+ for us, so I'm not sure there's anything to review as that's on par with the recommendations (and good it's actually enforced now) — did you mean anything beyond that?
My earlier comment was addressing the poster's recommendation to use at least ffdhe3072. That is not in scope for this PR and will be addressed in the future with specification review. :)
verify exim doesn't need removal of +no_ssl* flags
I verified the exim code.
decide on tomcat (that may or may not use openssl implementation…)
src/js/configs.js specifies usesOpenssl: false
review all use of output.usesDhe, output.dhCommand, output.dhParamSize
I did review this. Please be more specific for what you/I might look.
I wrote:
My earlier comment was addressing the poster's recommendation to use at least ffdhe3072. That is not in scope for this PR and will be addressed in the future with specification review. :)
I should note that some servers hard-code ffdhe2048. stunnel is one. I think postgresql was another. (I was not keeping track as I quickly reviewed source code for calls to SSL_CTX_set_dh_auto()
or SSL_set_dh_auto()
.)
lighttpd is a third, but lighttpd only uses ffdhe2048 if openssl version is too old. The reason I have not updated lighttpd is because if you're on an ancient system and using an ancient openssl version, you are probably on an underpowered system and you likely have many other system security risks more important than DHE bit length. If this is a concern, you should, of course, configure lighttpd with your own appropriate DHParameters
.
A large amount of time is being spent on DHParameters
, even though modern security recommendations do not include ciphers which require them. I do not think we would be spending time on this if the Mozilla TLS recommendations were reviewed and updated.
Note: https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/ recommends ECDHE and does not recommend any DHE ciphers, even for Legacy. (If TLSv1 and TLSv1.1 are needed, then weaker ciphers are made available for such Legacy use.)
add an AND helper for conditional blocks only (not) matching two values
That is an underlying code change which has not effect on the output. It should not be part of this PR and should be tested and rolled out separately, in a separate PR.
decide on tomcat (that may or may not use openssl implementation…)
As already stated, this is not an issue with the current code which sets usesOpenssl: false
. If you want to change that for Tomcat, that IS NOT PART OF THIS PR and should not block this PR.
verify oraclehttp support
I don't have access to test oraclehttp, but if someone reports an issue with the Old config and SECLEVEL=0, then we can add code to oraclehttp.hbs to filter out SECLEVEL=0. Please remember that this is for the Old config; the Old config is old and people are strongly discouraged from using it.
@janbrasna Please focus on the "minimum viable product" to approve this PR so that it can be deployed for testing. This PR does not bump the openssl version, so you'll continue to have plenty of time for turd polishing for the Old config after this PR is merged and deployed. Please move as many of your testing concerns as you can from this PR to #263
recommendation to use at least ffdhe3072
2048-bit is still plenty, using the hashrate of the bitcoin global network in 2024 I did some napkin math (see near end of comment for 2048-bit math) which calculated 54,000 years, but that was just against the entropy with the hashrate as operations. I don't have math on me from old notes for GFNS which also requires considerable resources beyond CPU at this scale, but IIRC the attack cost should be higher... thus really not pragmatic / worthwhile.
TLS 1.3 also supports ffdhe2048 as a minimum IIRC and that's auto-negotiated? Usually you only see a desire to use more because the user does not understand the math, or some regulation compliance has raised the bar without adequate justification (presumably as a precaution or external perception/expectation).
Rebased on master.
After discussion in meeting, I have removed the dh_auto changes from this PR. (Note, this also removed the update to Apache version). Removing the dh_auto changes from this PR preserve the existing behavior for Intermediate to explicitly set 2048-bit DHE key. TLSv1.3 uses RFC7919 negotiation to select Group, and whether or not and how to configure Groups (Curves) will be a separate discussion from this PR. In the ssl-config-generator, usesDhe
is not set for TLSv1.3.
The remaining commit in this PR sets @SECLEVEL=0
for "Old" config to support TLSv1 and TLSv1.1 for OpenSSL 3.x. (SECLEVEL=1 would be minimum needed for 1024-bit DHE key used by "Old" config.)
I have incorporated the two changes: 1) test usesOpenssl !== false
and 2) if (ciphers[0] === '@SECLEVEL=0') ciphers.shift();
unconditionally.
I'm not sure about Tomcat impact
No impact. Tomcat is configured in src/js/config.js with
usesOpenssl: false
and that is checked before addingSECLEVEL=0
Which doesn't change whether folks end up using OpenSSL or JSSE. I don't have enough working knowledge to infer how the connectors configure own OPENSSL_CONF
or the context from its own jdk/jre java.security
properties or -Djdk.*
args at env/startup etc. — I'm more looking at this whether we need to start listing some caveats when we don't know if such profile can be supported fully (like we do in caddy comments)
A large amount of time is being spent on
DHParameters
Because it's the most sensitive setting in the current outputs, and of the added value features we provide translating the guidelines into the configs.
even though modern security recommendations do not include ciphers which require them
Which is not true. All TLSv1.3 suites include them by default (even though they don't "advertise" the fact in the IANA naming, but it's defined directly in the RFC).
recommendation to use at least ffdhe3072
2048-bit is still plenty
@polarathene Ah, that came from someone who got bad rating from an automated test unrelated to these configs, it was grading against Dutch Internet Standards Platform, but that probably evaluates the government recommendations wrong anyways, as only 1024 should fail, 2048 is still allowed even after years of updates to their specs, although noted to "phase out" — but they have no instructions attached as to what that is supposed to mean, i.e. it's still listed nonetheless. (I'd see the requirement for 3072 more as a bug in the automation tool TBH.)
We still reflect what is in the current recommendations, and will try to do so even for RFC7919 groups, if we end up restricting them in the configs. (See #270 …)
We still reflect what is in the current recommendations, and will try to do so even for RFC7919 groups, if we end up restricting them in the configs.
Yeah, I mentioned some reasons for why someone might feel the need to use a higher key/group size but as per the napkin math, I really don't see it being necessary.
Given that TLS 1.3 will handle many connections these days and IIRC a client or server may restrict it's ability to only negotiate with a cipher using FFDHE 2048-bit, since TLS 1.3 doesn't allow you to exclude that (not since I last checked anyway?) it'd be accepted 🤔
Since it's a static group for any such TLS 1.3 connection negotiated with it, someone with the resources could attack that for an advantage. At which point some policy goes into place to forbid/change it, but as per the math I linked earlier it's not very pragmatic to pull that off:
Besides... what if someone has the equivalent of that global bitcoin hashrate of 750 EH/sec against RSA-2048 (110-bit)???:
# 110-bit (RSA 2048-bit) operations processed at a rate of 750EH/sec # divided by seconds in a thousand years (approx), provides thousand of years required ( ((2^110) / 750e18) / (60*60*24*365*1e3)) ) ~= 54.88
54,000 years!!! Panic! The LetsEncrypt certificate with 90 days of validity is in danger! Quick bump it up to RSA 3072-bit!
Don't try to bring in quantum computing either. For similar reasons to why the math for RSA above isn't valid (GNFS), there are certain resource requirements that offset the advantages you see parroted around.
The link provides more context/info for that, but you need an awfully large amount of computation and advancement to bring that attack into the realm of possibility, as covered in another part of my napkin math reference:
Also for the 750 EH/sec, we don't have the best data on power usage, but it's estimated at 170 TW hours of electricity per year. More than Ukraine outputs annually. At just 10x the size of current network, the power output would be nearing that of India, 30x would surpass the USA and 200x the entire planets output. To support 1000x the bitcoin network size requires producing more energy that you're going to get how?
The power required is sufficient to boil all the oceans on the planet, it's not something you can do stealthily even if we could compute an attack within our lifetimes.
Unfortunately we have silly articles like this 2024 Forbes one encouraging 3072-bit and citing quantum compute risks:
While these key sizes are currently deemed secure against brute force attacks by computers, they may not provide security against quantum computers. For instance, a quantum computer employing Shor's algorithm might potentially crack a 2048-bit RSA key within eight hours.
Which to anyone who knows better this is nonsense. We are a long way off having the necessary qubits (the hardware you see marketed these days tends to be a lot lower in actual qubits since many are used for error correction). While the compute time could go down, it doesn't magically mess with physics, the entropy is still there and the resource cost just shifts, time is only one resource to take into consideration.
NIST Recommendations: The National Institute of Standards and Technology (NIST) explicitly recommends the use of 3072-bit keys as part of their guidelines for quantum cryptography. Following these guidelines ensures compliance with recognized standards and industry best practices.
RSA keys, not FFDHE group parameters but close enough compute wise IIRC 😅
That's the sort of thing that'll make a push for bumping it up, regardless of the math. That increase is smaller than RSA 1024-bit to 2048-bit too (NIST has their own document on equivalent symmetric security strength).
If someone is using "Old", then the priority is not "best security practices"; the priority is compatibility with out-of-date, end-of-life, and/or unmaintained devices (or all of the above). TLSv1.2 was released in 2008, over 16 years ago. TLSv1.0 and TLSv1.1 have been formally deprecated since March 2021 in RFC8996. Hello! As I write this, over 3 1/2 years (!) has passed since March 2021 when RFC8996 was published.
Therefore, I am committing this change as proposed over two weeks ago. This change is small, and setting SECLEVEL=0
is required for OpenSSL 3.x to support TLSv1.0 and TLSv1.1 protocols.
Follow-ups for https://github.com/mozilla/ssl-config-generator/pull/256#issuecomment-2458504186 in #270 "Explicitly configure curves/groups from the guidelines"
oraclehttp and Tomcat are marked in ssl-config-generator src/js/configs.js
with usesOpenssl: false
and are out-of-scope for the changes propsed in this PR.
@janbrasna, your additions to the TODO list are out-of-scope for this PR. Please handle elsewhere:
TODO/OQ:
- [x] ~consider AND helper for conditional blocks only (not) matching two values~
- [x] move oraclehttp from mod_ssl to mod_ossl
- [ ] look into tomcat seclevel options (for both apr/openssl implementation and java policy?)
- [ ] how does e.g. BoringSSL like that (should not matter when it doesn't support some weak ciphers at all?)
libressl supports @SECLEVEL
. BoringSSL does not recognize @SECLEVEL
. While both try to provide some level of compatibility with common OpenSSL interfaces, neither are OpenSSL. libressl has its own version numbers. BoringSSL is Google-specific and the source code README.md very explicitly states: (https://boringssl.googlesource.com/boringssl)
BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.
Although BoringSSL is an open source project, it is not intended for general
use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing
so is likely to be frustrating because there are no guarantees of API or ABI
stability.
Updates to support OpenSSL 3.x
Resolves #188 Tracked in #260
Set SECLEVEL=0 in cipherstring for
old
output to allow TLSv1–v1.1 for OpenSSL 3.x~Hide DH parameters for servers calling OpenSSL interfaces
SSL_CTX_set_dh_auto()
orSSL_set_dh_auto()
to use RFC7919.~ (TLS1.2 will keep just ffdhe2048, TLS1.3 will have to limit curves/groups, followup TBD)TESTING: https://test-3x--mozsslconf-dev.netlify.app/#openssl=3.3.3&config=old&server=postgresql