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 firstname.lastname@example.org 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 email@example.com. 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 firstname.lastname@example.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.