Subject: 24.3; SSL/TLS with multiple man-in-the-middle vulnerabilities

From: Jens Lechtenboerger <[email-masked]>
Date: Mon, 10 Mar 2014 07:52:43 +0100

I'm using GNU Emacs 24.3.1.  This affects Gnus v5.13 as well as Ma
Gnus v0.9.

I'm using Emacs to send e-mail via smtpmail.el with
smtpmail-stream-type set to starttls, read e-mail via
imap with :port 993 and :stream ssl, and send/read news via port 563
with nntp-open-tls-stream for nntp-open-connection-function.

In all these cases, SSL/TLS "secured" connections are used that
accept any certificate without checking the CA.  Thus,
man-in-the-middle (MITM) attacks will be successful and will go
unnoticed.

I don't find that acceptable.  I vote to ship Emacs with certificate
checking by default.  That way, we would be protected from Mallory
with self-signed, forged keys.  I even vote for certificate pinning
by default, which can protect us from Mallory with "trusted" keys
(Mallory who pays, bribes, tricks, compels, forces, or operates an
official CA).  This can be accomplished via gnutls-cli with
trust-on-first-use:

gnutls-cli --tofu opens a TLS connection and asks whether the
certificate can be trusted.  If so, it is added to
~/.gnutls/known_hosts.  On subsequent connections, the presented
certificate is compared against the stored one; in case of
mismatches, the user is asked whether to trust the new one.  To
prevent the process from hanging while waiting for the user's reply,
option --strict-tofu (introduced in GnuTLS 3.2.12) can be used.
I'm describing my view on certificate pinning in general and some
details on TOFU with GnuTLS in more detail in my blog:
https://blogs.fsfe.org/jens.lechtenboerger/?p=208

For Emacs, here is my personal workaround (a real fix would
probably require a unified, secure-by-default treatment of TLS
throughout all libraries):

Smtpmail uses network-stream-open-starttls, which calls
gnutls-negotiate (from gnutls.el) later on.  The function
gnutls-negotiate has parameters VERIFY-HOSTNAME-ERROR and
VERIFY-ERROR, which might be useful to detect MITM attacks, yet they
are not used.

Also nntp-open-connection calls gnutls-negotiate without checking
certificates.

Thus, I disable gnutls.el entirely:
(if (fboundp 'gnutls-available-p)
    (fmakunbound 'gnutls-available-p))

However, the problem is not restricted to gnutls.el.
Once I disable that library, different fallbacks are used in
different libraries.

Smtpmail falls back to starttls-open-stream from starttls.el.
In my case, that library uses gnutls-cli, and --strict-tofu can be
added to starttls-extra-arguments:
(setq starttls-extra-arguments '("--strict-tofu"))

NNTP does not fall back to starttls.el but to open-tls-stream from
tls.el.  That library makes use of tls-program, which defaults to
gnutls-cli with the switch --insecure.  That switch is called
"insecure" for a good reason and should be removed, IMO.  Better
yet, enable certificate pinning:
(setq tls-program '("gnutls-cli --strict-tofu -p %p %h"))

The library imap.el makes use of openssl's s_client via
imap-ssl-program.  While s_client is great to debug SSL/TLS
connections, it is useless for everyday encryption as it prints an
error message if certificates cannot be verified, but it opens the
connection anyways.  And, those errors are not shown in Emacs.
So, switch to gnutls-cli with certificate pinning:
(setq imap-ssl-program '("gnutls-cli --strict-tofu -p %p %s"))

(Note that tls-program expects %h where imap-ssl-program uses %s.)

Best wishes
Jens