Re: Replay attack of query cancel

From: Magnus Hagander <magnus(at)hagander(dot)net>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Gregory Stark <stark(at)enterprisedb(dot)com>, Andrew Gierth <andrew(at)tao11(dot)riddles(dot)org(dot)uk>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: Replay attack of query cancel
Date: 2008-08-13 14:09:36
Message-ID: 48A2EB20.8020305@hagander.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Tom Lane wrote:
> Magnus Hagander <magnus(at)hagander(dot)net> writes:
>> What would work is using a parameter field, per Stephen's suggestion
>> elsewhere in the thread. Older libpq versions should just ignore the
>> parameter if they don't know what it is.
>
> +1 for that one; we have done it already for several send-at-startup
> parameters that didn't use to be there, eg standard_conforming_strings.
>
> I'd go with defining it as the maximum cancel version number
> supported, eg "cancel_version = 31", with the understanding that
> if it's not reported then 3.0 should be assumed.
>
> So the plan looks like this, I think:
>
> * Main FE/BE protocol doesn't change, but there might be an additional
> value reported in the initial ParameterStatus messages. We believe that
> this will not break any existing clients.
>
> * Server accepts two different styles of cancel messages, identified
> by different protocol numbers.

With the additional point that there is a GUC variable to turn this off
or warn about it, right?

> * Client decides which type to send based on looking for the
> cancel_version parameter.
>
> This seems back-patchable since neither old clients nor old servers
> are broken: the only consequence of using an old one is your cancels
> aren't sent securely, which frankly a lot of people aren't going
> to care about anyway.

Right. All those people running without SSL in the first place, for
example...

> Note after looking at the postmaster code: the contents of new-style
> cancel keys ought to be the backend PID in clear, the sequence number in
> clear, and the hash of backend PID + cancel key + sequence number.
> If we don't do it that way, the postmaster will need to apply the hash
> function for *each* backend to see if it matches, which seems like
> a lot more computation than we want. The postmaster needs to be able to
> identify which backend is the potential match before executing the hash.

Yes, certainly. Otherwise, the cost ends up a lot higher on the server
than the client, which is a really simple DOS opportunity.

> The main drawback I can see to keeping this backward-compatible is that
> keeping the cancel key to 32 bits could still leave us vulnerable to
> brute force attacks: once you've seen a cancel message, just try all
> the possible keys till you get a match, and then you can generate a
> cancel that will work. Can we refine the HMAC idea to defeat that?
> Otherwise we're assuming that 2^32 HMACs take longer than the useful
> life of a cancel key, which doesn't seem like a very future-proof
> assumption.

Well, you're also going to have to increment <n> every time. We could
just cap <n> at <arbitrary level>. Say you can only cancel queries on a
single connection a million times or so. It's not perfect, but it gets
you somewhere.

Another option would be to send a new, longer, cancel key as part of the
separate parameter we're sending during startup (when we're indicating
which version we support). Then we'll use the longer cancel key if we're
dealing with "new style cancel" but keep the old 32-bit one for
backwards compatibility.

//Magnus

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2008-08-13 14:18:09 Re: Replay attack of query cancel
Previous Message Tom Lane 2008-08-13 14:00:29 Re: Replay attack of query cancel