Advisory 01/2018: Multiple vulnerabilities in GnuPG/dirmngr regarding WKD

                            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.