SektionEins GmbH
www.sektioneins.de
-= Security Advisory =-
Advisory: CSRF/SSRF and DoS in GnuPG's WKD handling
Release Date: 23 November 2018
Last Modified: 05 December 2018
Author: Ben Fuhrmannek [ben.fuhrmannek[at]sektioneins.de]
Application: GnuPG
versions 2.1.18 - 2.2.9 for issue (1)
versions 2.1.12 - 2.2.11 for issue (1a)
versions 2.1.12 - 2.2.9 for issue (2)
versions 2.1.12 and upwards for issue (3)
Severity: The use of WKD key lookup via GnuPG's dirmngr can lead to
(1) arbitrary HTTPS GET requests via DNS SRV response
(1a) arbitrary HTTPS GET requests via HTTP redirect
(2) Denial-of-Service: memory exhaustion
(3) Denial-of-Service: Keyring pollution
Risk: Medium
Vendor Status: fixed: (1), (1a), (2); not fixed: (3)
Reference: https://www.sektioneins.de/en/advisories/advisory-012018-gnupg-wkd.html
Overview:
"Web Key Directories provide an easy way to discover public keys
through HTTPS." - WKD - GnuPG wiki (https://wiki.gnupg.org/WKD)
(1) A key can be imported from a web server. The web server's
hostname is resolved via DNS SRV query, but GnuPG fails to
properly sanitize the response, leading to arbitrary HTTPS GET
requests.
(2) In addition, the keyring to be downloaded is temporarily held
in memory, which may lead to memory exhaustion.
(1) Arbitrary HTTPS GET requests via DNS SRV response:
A common way to invoke a WKD request via GnuPG's dirmngr from CLI
is
gpg --auto-key-locate=clear,nodefault,wkd --locate-key info@example.com
This tries to resolve `_openpgpkey._tcp.example.com` via DNS. If
found, a URI is assembled, containing the DNS response's target
string (`<target>`) - supposedly a hostname - and port number
(`<port>`), like so:
https://<target>:<port>/.well-known/openpgpkey/hu/<hash>
`<hash>` is a zbase32 encoded hash value unique to the email
address.
A validation step tries to validate, that `<target>` is identical
to the original domain part of the lookup email address or
otherwise ends in '.' concatenated with the domain part (e.g.
'.example.com'). This validation step appears to be insufficient,
as it allows arbitrary characters before the correctly validated
domain part, e.g. '/' and '?'.
A malicious SRV record can point to arbitrary URLs. Example SRV
lookup:
$ host -t srv _openpgpkey._tcp.example.com.
_openpgpkey._tcp.example.com has SRV record 0 5 443 sektioneins.de/wkd-bug?.example.com.
The assembled URI would look like so:
https://sektioneins.de/wkd-bug?.example.com:443/.well-known/openpgpkey/hu/<hash>
In order to see more debug messages, the following lines can be
added to ~/.gnupg/dirmngr.conf:
verbose
debug 4096
debug-level 4096
debug-all
log-file /tmp/dirmngr.log
Limitations: The dirmngr's builtin HTTP client does a certificate
validation for HTTPS requests, thereby effectively limiting
requests to public domains. Internal addresses and private IP
addresses will most likely fail to provide a valid certificate
unless configured manually.
CSRF / SSRF:
Depending on how the WKD key lookup is triggered, this
vulnerability can be used to perform Cross-Site-Request-Forgery or
Server-Side-Request-Forgery respectively. For example,
Thunderbird/Enigmail tries to lookup keys via WKD by default and
may have been triggered by a mailto: link. This falls under the
category CSRF.
Any server side key lookup via WKD may be vulnerable to SSRF
depending on the exact software used.
Recommendation:
The SRV record must be validated before being used as part of a
URI. This issue was resolved with version 2.2.10.
(1a) arbitrary HTTPS GET requests via HTTP redirect:
A variation of (1) is to redirect a legitimate WKD request to
another URL via HTTP Code 301, 302 or 307. There are effective
checks for redirect loops and https to http downgrade. However the
target location can be arbitrary and as such it can be used to
trigger CSRF/SSRF as described above.
Consider a web service of some kind with IP restrictions, that can
only be accessed from within a company's network. The redirect
target would be this protected resource and can now be triggered
via WKD on another domain.
Silly example:
1. WKD GET https://foo.bar/.well-known/... redirects to
https://cluster.example.com/rest/shutdown?when=now
2. cluster.example.com checks originating IP.
3. Request originates from company network, so shutdown is executed.
Of course, even offering such a hypothetical REST service would
leave the company open to CSRF attacks in the first place. But
being able to trigger the CSRF via WKD, potentially without the
user's knowledge as this attack vector is not widely known, is
GnuPG's shortcoming.
Recommendation:
There are several ways to prevent this attack. A few examples:
* some equivalent to a web browser's CORS policy: The target should be
able to specify, whether 302 should have been allowed, e.g. by stating
so in the policy file.
* the target URI could be stripped down to host/port components and be
used to construct the usual https://host:port/.well-known/... URI
* or simply deactivate 30x to other domains.
This issue was fixed and will be released with the next version 2.2.12.
(2) Denial-of-Service: memory exhaustion:
A keyring downloaded via WKD is temporarily stored in memory
without size limitation. This may lead to memory exhaustion and
the graceful termination of gpg:
gpg: error reading key: Cannot allocate memory
Other processes running on the same system may be affected as
well.
Recommendation:
A suitable download limit should be in place. This issue was
resolved with version 2.2.10.
(3) Denial-of-Service: multiple key imports / keyring pollution:
A keyring downloaded via WKD may contain any number of keys
matching the lookup request. All matching keys are imported to the
active keyring, leading to an unnecessary number of useless keys.
This issue is mostly an annoyance for the user, but may impact
hard disk space and GnuPG overall performance. Also, keep in mind,
that keys may be imported in the background without the user
knowing, e.g. via an auto-import feature of email clients.
Recommendations: There are several ideas to be considered. (a)
Automatically downloaded keys could be stored in a separate
keyring. (b) An import history may help to delete the last 'X'
imports. (c) There could be an import limit for downloaded keys.
Recommendation for users:
It is possible to restrict key lookups by appending this line to
your gpg.conf:
auto-key-locate clear,local
Note: This will disable the WKD service entirely and does not
protect against manual key imports.
Disclosure Timeline:
26 July 2018:
Contacted security@gnupg.org.
27 July 2018 - received comments from developer:
"Given that WKD is an experimental service I would not considre
this a as High, YMMV." - Even 'experimental' features can be a
high security risk when enabled. However given the difficulty to
successfully exploit this CSRF-style vulnerability in combination
with vulnerable web-applications, likely only very few
installations will be affected in a negative way, so the risk was
reevaluated to Medium.
Issue (1) was solved with commit-ids ebe727e and ddee9f9.
Regarding (2): "... For WKD we can indeed set an upper limit
becuase we already use a 65 KiB limit in the gpg-wks."
Regarding recommendations for (2): "Pretty bad recommendation as
it will disable this service . And it does not help against the
standard pracise of downloading keys from a keyserver or import
attached keys from a received mail. Even not with that autocrypt
thing (which can be modified on the fly)." - A note was added to
the recommendation.
Regarding (3): "That is by design to allow key-rollover." - Even
though I see this as a problem related to (1) and (2), this issue
is not directly related to the other issues and was removed from
the advisory.
30 August 2018:
GnuPG 2.2.10 was released, which includes fixes for issue (1) and
(2).
August - November 2018:
More research was performed.
20 November 2018:
Issue (3) was re-added after careful consideration. Keyring
pollution can be a seriously annoying denial of service attack,
especially when downloaded in the background without the user's
knowledge. A common scenario would be a setup of
Enigmail/Thunderbird with WKD enabled by default. After the
recipient's email address is entered in the To:/Cc:/Bcc: field of
a composer window, the WKD request is started automatically in the
background without any further user interaction.
A fourth issue (1a) was added as a variation of (1).
Contacted security@gnupg.org.
21 November 2018:
Added more details and examples to issue (1a).
23 November 2018:
Comments form developer regarding issue (1a):
"The protection I implemented for 2.2 (and master) is commit
4a4bb874f63741026bd26264c43bb32b1099f060
dirmngr: Avoid possible CSRF attacks via http redirects.
With this change a http query will not follow a redirect unless
the Location header gives the same host. If the host is different
only the host and port is taken from the Location header and the
original path and query parts are kept.
I view this as strict enough and still keeping redirection working
in most cases. Given the overall problematic of possible redirect
attacks due to a wide range of scripts, I don't think that this
fix requires an urgent security release. There will be a release
in a few weeks anyway."
Released advisory.
05 December 2018:
Added assigned CVE id.
CVE Information:
The Common Vulnerabilities and Exposures project (cve.mitre.org)
has assigned CVE id CVE-2018-1000858 via Distributed Weakness
Filing (DWF).
GPG-Key:
pub rsa4096 2018-09-06 [SC] [expires: 2021-03-04]
0603B59886CA3089E8FDBBD02E912C44650AD2AF
Copyright 2018 SektionEins GmbH. All rights reserved.