Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Downgrade protection for Opportunistic Security schemes for SMTP #178

Open
foxcpp opened this issue Dec 12, 2019 · 1 comment
Open

Downgrade protection for Opportunistic Security schemes for SMTP #178

foxcpp opened this issue Dec 12, 2019 · 1 comment
Labels
mta-in Related to incoming message processing part of the MTA functionality (mail exchanger). mta-out Related to MSA or outgoing message processing part of MTA functionality. rfc Request For Comments (ongoing discussion / research needed). security Related to security measures.

Comments

@foxcpp
Copy link
Owner

foxcpp commented Dec 12, 2019

Transport security in SMTP world is merely Opportunistic, there is no practice like in the Web to always require encryption with matching DNS-ID and trusted certificate. Additionally, things get complicated with the use of MX records to delegate mail handling.

Overall, here are possible options for each SMTP connection, sorted by protection "strength":

  • No encryption (no protection altogether).
  • TLS without authentication e.g. self-signed cert. (protects against passive attacks only, server key can be spoofed)
  • TLS with server cert. authentication (protects against passive attacks, MX records can be spoofed)
  • TLS with server cert. authentication and DNSSEC (protects against passive attacks, STARTTLS support can be spoofed to downgrade connection to plaintext)
  • TLS with server cert. authentication and MTA-STS (protects against passive and active attacks, but policy expiry makes it unreliable)
  • TLS with server cert. authentication and DNSSEC+DANE (protects against active and passive attacks, best option)

Each of these options is better than the previous one so it makes sense to support all of them without directly falling back to the weakest one (no encryption).

Interaction with REQUIRETLS

SMTP REQUIRETLS extension requires TLS with valid and matching certificates and MX records authentication using either DNSSEC or MTA-STS. So messages using it are handled in a "strongest security or fail delivery" way instead of Opportunistic Security approach typically employed by MTAs.

Though, MTA-STS and DANE have similar but not same security characteristics (as was noted in the draft spec review, see References). This might degrade the actual security provided by extension in the long term if DANE becomes more widespread than MTA-STS (unlikely).

Proposal

  1. Implement REQUIRETLS extension (issue SMTP REQUIRETLS support #123)

  2. Provide policy options to require certain security level for all messages (already done, see authenticate_mx, require_mx_auth and require_tls directives for remote module).

  3. (Possibly) Implement downgrade protection for non-REQUIRETLS messages by remembering the authentication/encryption status like chasquid does it.
    It will help with messages sent without using REQUIRETLS extension (as practice shows, SMTP extensions support is poor and grows slowly). Though, it is not clear whether to group options by protection scope (passive/active attacks) for simplicity or provide high granularity. Later option may be better for security but also increases the chance of unexpected interactions.

References

@foxcpp foxcpp added security Related to security measures. rfc Request For Comments (ongoing discussion / research needed). mta-out Related to MSA or outgoing message processing part of MTA functionality. mta-in Related to incoming message processing part of the MTA functionality (mail exchanger). labels Dec 12, 2019
@foxcpp
Copy link
Owner Author

foxcpp commented Dec 12, 2019

Another option:

  • Matching TLSA record with DANE-TA (Usage 2) or DANE-EE (Usage 3) can replace PKIX and ServerName checks and provides the essentially same (or even stronger) protection against active attacks.

Observation: Most deployed TLSA records use DANE-EE.

@foxcpp foxcpp pinned this issue Dec 12, 2019
foxcpp added a commit that referenced this issue Dec 13, 2019
TLS without authentication is still better than no TLS at all.

To save latency in transactions with a misconfigured recipient server
that cannot use TLS at all but still advertises STARTTLS support,
downgrade to non-authenticated TLS is attempted only on verification
errors (x509.UnknownAuthorityError or x509.HostnameError) and malformed
certificate errors (x509.ConstraintViolationError and
x509.CertificateInvalidError). In all other cases 'remote' module
fallbacks to plaintext directly.

While rearranging code to support this, some additional changes were
made to allow simplier implementation of security levels idea from #178.

See https://tools.ietf.org/html/rfc7435.
See #178.
foxcpp added a commit that referenced this issue Dec 13, 2019
Previous approach consisted of multiple independent options with unknown
interaction between each other and not offering enough flexibility for
local policy configuration.

Additionally, it was not possible to implement downgrade protection
mentioned in #178 because it was not clear what is "downgrade" since
options were not related in any linear order, this commit makes it
explicit via the "security levels" system:
MX: DNSSEC > MTA-STS > Nothing
TLS: Authenticated+Encrypted > Encrypted > Plaintext

Note DNSSEC and MTA-STS being different levels, they provide different
security guarantees. Keeping them together under "authenticated" level
would not provide enough granularity for levels-based downgrade
protection and local policies.

'common_domain' MX authentication option is removed. It was offering no
real protection and therefore is was problematic to use together with
planned downgrade protection.

All security level errors are marked as temporary to force requeueing
and allow local admin to troubleshoot them without losing messages.

'remote' tests are changed to use testTarget function to initialize
tested module instance, since security levels mapping requires some
pre-initialization.

Support for IP literals in address domain-part is disabled because it
is incompatible with the new verification logic and was broken anyway
(#176).
@foxcpp foxcpp added this to the X.Y - "Eventually" milestone Feb 10, 2020
@foxcpp foxcpp removed this from the X.Y - "Eventually" milestone Jul 16, 2020
@foxcpp foxcpp unpinned this issue Jul 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mta-in Related to incoming message processing part of the MTA functionality (mail exchanger). mta-out Related to MSA or outgoing message processing part of MTA functionality. rfc Request For Comments (ongoing discussion / research needed). security Related to security measures.
Projects
None yet
Development

No branches or pull requests

1 participant