[kwlug-disc] Fwd: Postgresql hash index as a mitigation of timing attack

Mikalai Birukou mb at 3nsoft.com
Tue Jun 12 17:30:02 EDT 2018


The following is an in-depth analysis of the topic by Tim McLean 
(https://www.chosenplaintext.ca/). Posting his thoughts with the permission.

***

Hmmmmm, this is an interesting question!
It seems like it would depend significantly on how postgres implements 
the index. I think it would definitely make the attack harder.

It looks like 'hash' indexes in postgres are implemented using linear 
hashing: 
https://github.com/postgres/postgres/tree/master/src/backend/access/hash
Roughly, a hash function /H/ is applied to a key /k/ (in our case, k = 
the session id), and the last /b/ bits of /H/(/k/) are used to determine 
the memory address of one of 2^/b/ buckets.
Inside the bucket, a binary search is used to find the entry matching 
/H/(/k/).
(There's also some fancy stuff going on to handle adding more buckets as 
the index grows in size, so /b/ will change over time, but that's not 
too relevant here)

So it seems like timing attacks could discover a fair bit of information 
about /H/(/k/). Cache timing attacks could figure out which bucket was 
accessed, and maybe where in the bucket the binary search ended up at. 
Also, the binary search might involve comparisons that are not timing safe.

Now, learning /H/(/k/) might not be useful to the attacker, since hash 
functions can be irreversible. So, what is /H/?

/H/ seems to be a custom hash function design: 
https://github.com/postgres/postgres/blob/73b7f48f78d27b1baf1a6541cbaae0fe6bd6186d/src/backend/access/hash/hashfunc.c#L332
Since it's not a cryptographic hash, the normal security guarantees do 
not apply. Learning /H/(/k/) might reveal useful info about /k/! So that 
may be a problem.

(Aside: this all makes me wonder if postgres is vulnerable to a denial 
of service attack where an attacker purposely supplies values that all 
hash to the same bucket index, forcing worst-case performance?)

Another thought that I have: if /H/ is weak enough, then once we have 
learned /H/(/k/), we may be able to generate preimages (other values 
that have the same hash) that look like session ids.
So we can generate /k/_0, /k/_1, ..., /k/_F such that /H/(/k/_0) = 
/H/(/k/_1) = ... = /H/(/k/_F) = /H/(/k/). In other words, we find a 
bunch of session id strings that hash to the right value.
Maybe we can make it so that /k/_0 starts with '0', /k/_1 starts with 
'1', ..., /k/_F starts with 'F'.
My understanding is that, if we try a session id that has the right hash 
value, postgres will access the right bucket, find the entry with the 
real session id, and then do a string comparison between the real 
session id with the session id that was provided. This comparison 
probably isn't timing safe!

I don't know if this attack would work though, since it really depends 
on how strong /H/ is.

***

How about a different solution? Let's assume the session ids are 
generated using a cryptographically secure random number generator and 
have 128 bits of entropy (e.g. 16 bytes encoded as 32 hex chars).

If we hash the session id with a cryptographic hash (say, SHA-256), it 
would be impossible to figure out the session id from looking at the 
hash (it would take 2^127 guesses on average, and the world doesn't have 
enough electricity to do this many calculations -- no need for a 
password hash here).

So what if, instead of storing the session id in the database, we store 
`sha256(session_id)` instead? When we get a session id from a client, we 
hash the session id and do a database query with the hash.

The database might do a string comparison that leaks information about 
the hash -- that's fine. Even if the attacker gets the full hash, they 
still can't figure out the session id. The only code at risk for timing 
attacks now is the piece that receives the session id from the client 
and hashes it with SHA-256. It's unusual to see timing leaks in SHA-256 
though, so that's unlikely to be a problem.

The important piece here is that the server must do the hashing. If we 
do the session id hashing on the client side, then we're back to the 
original problem again :)

Tim

On Wed, Jun 6, 2018 at 3:00 PM, Mikalai Birukou <mb at 3nsoft.com 
<mailto:mb at 3nsoft.com>> wrote:

    Hi Tim,

    Following timing attacks thoughts and a recent KWLUG talk about
    Postgresql db, the following idea came to mind. What do you think?

    Cheers.

    -------- Forwarded Message --------

    Context (as a follow up to Hadi's presentation on the 4-th of June):

    Sometimes we store secret session ids in db, and we use these for
    authentication. Usually there is query that get respective record,
    searching a table for a given by user session id.
    Usual `WHERE` clause uses the most fast comparison, which run timing is
    dependent on input values. This can be used as a base for an attack with
    session id guessing via timing.

    Question:

    Hadi, and others, will hash index work as a quick fix here?

    1) Should ensure that a query, abusable by an attack, always uses index.

    2) Index on a secret (e.g. session id) is a hash index. I assume it
    means that provided by a user (attacker) value is hashed, and fast
    comparison will occur on hashes.
    Hashes that are close to each other, like `a...`, `aD...`, `aDf...`,
    which is a guessing sequence will be coming from values that are not
    very close to each other. Unless hash has a simple unhash function,
    there seem to be no way to arrange guessing sequence on an attacking
    side.

    If both 1 and 2 are achievable, then a simple switch to hash index can
    be a mitigation.
    Whereas, the other way, as heard on one of ProtonMail's tech talks, is
    for developer to split a secret token into two part, with only first
    part being used in `WHERE` clause, while biz app does constant time
    comparison of the second part.

    _______________________________________________
    kwlug-disc mailing list
    kwlug-disc at kwlug.org <mailto:kwlug-disc at kwlug.org>
    http://kwlug.org/mailman/listinfo/kwlug-disc_kwlug.org
    <http://kwlug.org/mailman/listinfo/kwlug-disc_kwlug.org>


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://kwlug.org/pipermail/kwlug-disc_kwlug.org/attachments/20180612/97d36c02/attachment.htm>


More information about the kwlug-disc mailing list