Keyserver/security bug 1447 (and 1446 too)
Phil Pennock
gnupg-devel at spodhuis.org
Mon Dec 3 04:55:54 CET 2012
On 2012-12-02 at 12:57 -0500, David Shaw wrote:
> On Dec 2, 2012, at 12:34 AM, Phil Pennock <gnupg-devel at spodhuis.org> wrote:
> > This first bug (1447) is a security-impacting bug; not too bad, since
> > PGP has message-level security, so the key data isn't impacted, but it
> > does permit MitM attacks for discerning what's happening. GnuPG uses
> > data from insecure DNS for presenting to an HTTPS-enabled keyserver as
> > TLS SNI and for verifying certificates. So if DNS responses are
> > tampered with, the injected bad server will verify fine for the client.
>
> Allow me to restate the problem to make sure I understand what you're
> saying. GnuPG does a SRV lookup for hkps under (for example)
> my-hkps-pool.example.com, and resolves to
> some-keyserver-in-the-pool.example.net. It then makes a https call to
> that host, but is using keyserver-in-the-pool.example.net as the SNI,
> as that matches the host name. You are arguing that it should have
> used my-hkps-pool.example.com as the SNI?
Correct. That's the only verifiably trustworthy name available. All
other names could have been tampered with, without detection (unless
DNSSEC is in use and verified).
> If that's the issue, I agree that is not ideal. It's sort of a side
> effect of how we're doing SRV with Curl. Since Curl doesn't do SRV at
> all, we have a wrapper around libcurl that does a minimal emulation of
> true SRV and then forces the URL to be what it should be, according to
> the SRV.
I hear you. Sounds truly awkward with some kludging needed to fix. As
an application maintainer who has to work around library awkwardness
myself, you have my sympathy.
> As far as I know, libcurl uses the host from the passed-in URL for SNI
> and there isn't a direct option to set the SNI to an arbitrary value,
> but looking at the options, CURLOPT_RESOLVE could be used to fix this
> by feeding in a record with the pool name and the address of the
> chosen server.
That matches what I've done on the curl(1) command-line to test the
setup in the past. I concur, I can't find an API to hook into DNS
resolution to change things otherwise, nor to change the SNI presented.
Looks like CURLOPT_RESOLVE is the only available mechanism.
So, as I understand it, to handle SRV, ports and SNI in combination,
it's:
* take the original hostname OHost
* look for SRV record for _pgpkey-http/_pgpkey-https._tcp.$OHost,
ignore this logic if neither SRV is found because we're connecting to
something where the hostname resolves directly to what's neeeded
* for each SRV record, take the hostname and port
* resolve the per-srv-record hostname to IP addresses
* iterate for each IP address:
* construct a curl_slist, populate with one triple of
$OHost:per-srv-record-Port:IP-Address
* curl_easy_setopt() with CURLOPT_RESOLVE to set that triple
* attempt to connect with curl, on the port from SRV, using the
$OHost hostname
* curl_easy_setopt()/CURLOPT_RESOLVE/ "-$OHost:per-srv-record-Port"
There doesn't appear to be a way to provide multiple IPs for one
hostname.
Curl_loadhostpairs() shows that the clean-up is overkill, but I'm not
confident in the resiliency of this API to a later change to permit
multiple records for one hostname, especially since some of the usage
comments don't even include the port field.
> Ideally, libcurl would handle SRVs internally,
Complete APIs from a library? Any library? Thou jesteth.
Sorry to have been the bearer of bad news about the size of the can of
worms you opened when adding SRV support.
-Phil
More information about the Gnupg-devel
mailing list