Antoine Beaupr : CVE-2020-13777 GnuTLS audit: be scared
So CVE-2020-13777 came out while I wasn't looking last week. The
GnuTLS advisory (GNUTLS-SA-2020-06-03) is pretty opaque so I'll
refer instead to this tweet from @FiloSottile (Go team
security lead):
Affected packages
Assuming you're running Debian, this will show a list of packages that
PSA: don't rely on GnuTLS, please. CVE-2020-13777 Whoops, for the past 10 releases most TLS 1.0 1.2 connection could be passively decrypted and most TLS 1.3 connections intercepted. Trivially. Also, TLS 1.2 1.0 session tickets are awful.You are reading this correctly: supposedly encrypted TLS connections made with affected GnuTLS releases are vulnerable to passive cleartext recovery attack (and active for 1.3, but who uses that anyways). That is extremely bad. It's pretty close to just switching everyone to HTTP instead of HTTPS, more or less. I would have a lot more to say about the security of GnuTLS in particular -- and security in general -- but I am mostly concerned about patching holes in the roof right now, so this article is not about that. This article is about figuring out what, exactly, was exposed in our infrastructure because of this.
Affected packages
Assuming you're running Debian, this will show a list of packages that
Depends
on GnuTLS:
apt-cache --installed rdepends libgnutls30 grep '^ ' sort -u
This assumes you run this only on hosts running Buster or
above. Otherwise you'll need to figure out a way to pick machines
running GnuTLS 3.6.4 or later.
Note that this list only first level dependencies! It is perfectly
possible that another package uses GnuTLS without being listed
here. For example, in the above list I have libcurl3-gnutls
, so the
be really thorough, I would actually need to recurse down the
dependency tree.
On my desktop, this shows an "interesting" list of targets:
apt
cadaver
- AKA WebDAV
curl
& wget
fwupd
- another attack on top of this one
git
(through the libcurl3-gnutls
dependency)
mutt
- all your emails
weechat
- your precious private chats
Arguably, fetchers like apt
, curl
, fwupd
, and wget
rely on HTTPS for
"authentication" more than secrecy, although apt
has its own
OpenPGP-based authentication so that wouldn't matter anyways. Still,
this is truly distressing. And I haven't mentioned here things like
gobby
, network-manager
, systemd
, and others - the scope of this is
broad. Hell, even good old lynx
links against GnuTLS.
In our infrastructure, the magic command looks something like this:
cumin -o txt -p 0 'F:lsbdistcodename=buster' "apt-cache --installed rdepends libgnutls30 grep '^ ' sort -u" tee gnutls-rdepds-per-host awk ' print $NF ' sort uniq -c sort -n
There, the result is even more worrisome, as those important packages seem to rely on GnuTLS for their transport security:
mariadb
- all MySQL traffic and passwords
mandos
- full disk encryption
slapd
- LDAP passwords
mandos
is especially distressing although it's probably not
vulnerable because it seems it doesn't store the cleartext -- it's
encrypted with the client's OpenPGP public key -- so the TLS tunnel
never sees the cleartext either.
Other reports have also mentioned the following servers link
against GnuTLS and could be vulnerable:
exim
rsyslog
samba
- various
VNC
implementations
Not affected
Those programs are not affected by this vulnerability:
apache2
gnupg
python
nginx
openssh
This list is not exhaustive, naturally, but serves as an example of
common software you don't need to worry about.
The vulnerability only exists in GnuTLS, as far as we know, so
programs linking against other libraries are not vulnerable.
Because the vulnerability affects session tickets -- and those are set
on the server side of the TLS connection -- only users of GnuTLS as a
server are vulnerable. This means, for example, that while weechat
uses GnuTLS, it will only suffer from the problem when acting as a
server (which it does, in relay mode) or, of course, if the remote IRC
server also uses GnuTLS. Same with apt, curl, wget, or git: it is
unlikely to be a problem because it is only used as a client; the
remote server is usually a webserver -- not git itself -- when using
TLS.
Caveats
Keep in mind that it's not because a package links against GnuTLS that
it uses it. For example, I have been told that, on Arch Linux, if
both GnuTLS and OpenSSL are available, the mutt
package will use the
latter, so it's not affected. I haven't confirmed that myself nor have I
checked on Debian.
Also, because it relies on session tickets, there's a time window
after which the ticket gets cycled and properly initialized. But that
is apparently 6 hours by default so it is going to protect only
really long-lasting TLS sessions, which are uncommon, I would argue.
My audit is limited. For example, it might have been better to walk
the shared library dependencies directly, instead of relying on Debian
package dependencies.
Other technical details
It seems the vulnerability might have been introduced in this merge
request, itself following a (entirely reasonable) feature request
to make it easier to rotate session tickets. The merge request was
open for a few months and was thoroughly reviewed by a peer before
being merged. Interestingly, the vulnerable function
(_gnutls_initialize_session_ticket_key_rotation
), explicitly says:
* This function will not enable session ticket keys on the server side. That is done
* with the gnutls_session_ticket_enable_server() function. This function just initializes
* the internal state to support periodical rotation of the session ticket encryption key.
In other words, it thinks it is not responsible for session ticket
initialization, yet it is. Indeed, the merge request fixing the
problem unconditionally does this:
memcpy(session->key.initial_stek, key->data, key->size);
I haven't reviewed the code and the vulnerability in detail, so take
the above with a grain of salt.
The full patch is available here. See also the upstream issue
1011, the upstream advisory, the Debian security
tracker,
and the Redhat Bugzilla.
Moving forward
The impact of this vulnerability depends on the affected packages and
how they are used. It can range from "meh, someone knows I downloaded
that Debian package yesterday" to "holy crap my full disk encryption
passwords are compromised, I need to re-encrypt all my drives",
including "I need to change all LDAP and MySQL passwords".
It promises to be a fun week for some people at least.
Looking ahead, however, one has to wonder whether we should follow
@FiloSottile's advice and stop using GnuTLS altogether. There are
at least a few programs that link against GnuTLS because of the
OpenSSL licensing oddities but that has been first announced in
2015, then definitely and clearly resolved in 2017 -- or maybe
that was in 2018? Anyways it's fixed, pinky-promise-I-swear,
except if you're one of those weirdos still using GPL-2, of
course. Even though OpenSSL isn't the simplest and secure TLS
implementation out there, it could preferable to GnuTLS and maybe we
should consider changing Debian packages to use it in the future.
But then again, the last time something like this happened, it was
Heartbleed and GnuTLS wasn't affected, so who knows... It is
likely that people don't have OpenSSL in mind when they suggest moving
away from GnuTLS and instead think of other TLS libraries like
mbedtls (previously known as PolarSSL), NSS, BoringSSL,
LibreSSL and so on. Not that those are totally sinless either...
"This is fine", as they say...
apt-cache --installed rdepends libgnutls30 grep '^ ' sort -u
apt
cadaver
- AKA WebDAVcurl
& wget
fwupd
- another attack on top of this onegit
(through the libcurl3-gnutls
dependency)mutt
- all your emailsweechat
- your precious private chatscumin -o txt -p 0 'F:lsbdistcodename=buster' "apt-cache --installed rdepends libgnutls30 grep '^ ' sort -u" tee gnutls-rdepds-per-host awk ' print $NF ' sort uniq -c sort -n
mariadb
- all MySQL traffic and passwordsmandos
- full disk encryptionslapd
- LDAP passwordsexim
rsyslog
samba
VNC
implementationsapache2
gnupg
python
nginx
openssh
weechat
uses GnuTLS, it will only suffer from the problem when acting as a
server (which it does, in relay mode) or, of course, if the remote IRC
server also uses GnuTLS. Same with apt, curl, wget, or git: it is
unlikely to be a problem because it is only used as a client; the
remote server is usually a webserver -- not git itself -- when using
TLS.
Caveats
Keep in mind that it's not because a package links against GnuTLS that
it uses it. For example, I have been told that, on Arch Linux, if
both GnuTLS and OpenSSL are available, the mutt
package will use the
latter, so it's not affected. I haven't confirmed that myself nor have I
checked on Debian.
Also, because it relies on session tickets, there's a time window
after which the ticket gets cycled and properly initialized. But that
is apparently 6 hours by default so it is going to protect only
really long-lasting TLS sessions, which are uncommon, I would argue.
My audit is limited. For example, it might have been better to walk
the shared library dependencies directly, instead of relying on Debian
package dependencies.
Other technical details
It seems the vulnerability might have been introduced in this merge
request, itself following a (entirely reasonable) feature request
to make it easier to rotate session tickets. The merge request was
open for a few months and was thoroughly reviewed by a peer before
being merged. Interestingly, the vulnerable function
(_gnutls_initialize_session_ticket_key_rotation
), explicitly says:
* This function will not enable session ticket keys on the server side. That is done
* with the gnutls_session_ticket_enable_server() function. This function just initializes
* the internal state to support periodical rotation of the session ticket encryption key.
In other words, it thinks it is not responsible for session ticket
initialization, yet it is. Indeed, the merge request fixing the
problem unconditionally does this:
memcpy(session->key.initial_stek, key->data, key->size);
I haven't reviewed the code and the vulnerability in detail, so take
the above with a grain of salt.
The full patch is available here. See also the upstream issue
1011, the upstream advisory, the Debian security
tracker,
and the Redhat Bugzilla.
Moving forward
The impact of this vulnerability depends on the affected packages and
how they are used. It can range from "meh, someone knows I downloaded
that Debian package yesterday" to "holy crap my full disk encryption
passwords are compromised, I need to re-encrypt all my drives",
including "I need to change all LDAP and MySQL passwords".
It promises to be a fun week for some people at least.
Looking ahead, however, one has to wonder whether we should follow
@FiloSottile's advice and stop using GnuTLS altogether. There are
at least a few programs that link against GnuTLS because of the
OpenSSL licensing oddities but that has been first announced in
2015, then definitely and clearly resolved in 2017 -- or maybe
that was in 2018? Anyways it's fixed, pinky-promise-I-swear,
except if you're one of those weirdos still using GPL-2, of
course. Even though OpenSSL isn't the simplest and secure TLS
implementation out there, it could preferable to GnuTLS and maybe we
should consider changing Debian packages to use it in the future.
But then again, the last time something like this happened, it was
Heartbleed and GnuTLS wasn't affected, so who knows... It is
likely that people don't have OpenSSL in mind when they suggest moving
away from GnuTLS and instead think of other TLS libraries like
mbedtls (previously known as PolarSSL), NSS, BoringSSL,
LibreSSL and so on. Not that those are totally sinless either...
"This is fine", as they say...
_gnutls_initialize_session_ticket_key_rotation
), explicitly says:
* This function will not enable session ticket keys on the server side. That is done
* with the gnutls_session_ticket_enable_server() function. This function just initializes
* the internal state to support periodical rotation of the session ticket encryption key.
In other words, it thinks it is not responsible for session ticket
initialization, yet it is. Indeed, the merge request fixing the
problem unconditionally does this:
memcpy(session->key.initial_stek, key->data, key->size);
I haven't reviewed the code and the vulnerability in detail, so take
the above with a grain of salt.
The full patch is available here. See also the upstream issue
1011, the upstream advisory, the Debian security
tracker,
and the Redhat Bugzilla.