Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

RavenDB Security Review: Non-Constant Time Secret Comparison

DZone's Guide to

RavenDB Security Review: Non-Constant Time Secret Comparison

Once this was pointed out, I was cringing inside because it was obvious what was wrong and I knew it was wrong, and we still had it in the code (which is why audits are great).

· Database Zone ·
Free Resource

RavenDB vs MongoDB: Which is Better? This White Paper compares the two leading NoSQL Document Databases on 9 features to find out which is the best solution for your next project.  

This issue was the simplest to fix in the RavenDB security report finding. Here is what the code looks like:

[DllImport("msvcrt.dll", EntryPoint = "memcmp")]
[SecurityCritical]
public static extern int Compare(byte* b1, byte* b2, long count);


fixed (byte* pExistingKey = existingKey)
{
  bool areEqual = Compare(pKey, pExistingKey, key.Length) == 0;
  Sodium.ZeroMemory(pExistingKey, key.Length);
}

And once it was pointed out, I was cringing inside because it was both obvious what was wrong and I knew it was wrong, and we still had this in the code (which is why audits are great).

What is the problem here? Conceptually, this is what this method does:

while (last > 0)
{
    if (*((byte*)bpx) != *((byte*)bpy))
    {
        return false;
    }

    bpx++;
    bpy++;
    last--;
}

This works perfectly — except that it leaks information to a potential attack. In particular, it leaks timing data. You might expect that the time spent comparing a couple of 32 bytes values wouldn’t matter, given that an attack is probably over a network connection, but it does. There is a great paper that shows how you can use such timing attacks to get private keys information.

In short, anything that uses security needs to use constant time comparisons. Again, conceptually, this means changing the code to be:

bool match = true;
while (last > 0)
{
    if (*((byte*)bpx) != *((byte*)bpy))
    {
        match = false;
    }

    bpx++;
    bpy++;
    last--;
}
return match;

So, regardless of the result, we’ll always do the same amount of work and won’t expose details through different processing times. In general, by the way, algorithms and execution of code in cryptography attempt to avoid anything that branches on the secret information, because that leaks details to attackers. This is also why AES cannot be securely implemented in software — you always leak in that mode.

The fix, by the way, was to use the sodium_memcmp, which ensures constant time operation.

Get comfortable using NoSQL in a free, self-directed learning course provided by RavenDB. Learn to create fully-functional real-world programs on NoSQL Databases. Register today.

Topics:
database ,timing attacks ,database security ,data leak

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}