brockallen / BrockAllen.MembershipReboot

MembershipReboot is a user identity management and authentication library.
Other
742 stars 238 forks source link

Discovering usernames via authentication timing #610

Closed nicholas-brooks closed 8 years ago

nicholas-brooks commented 8 years ago

Hi Brock.

Just found this while doing some testing on our authentication app. When you attempt to sign in with a valid username the authentication process can take > 500ms regardless of whether the password is correct or not due to the entered password being hashed (depending on hashing iterations).

However if you attempt to sign in with an invalid username, the sign in process returns 'immediately'.

So using this approach you can in theory discover what valid usernames are (or emails, if emails are the usernames) based on how long the sign in process takes.

Do you have any suggestions on how to mitigate this information leakage?

I was thinking of if no user was found with the username entered, to then hash a random string using the current password hashing method.

Thoughts?

cbomkamp commented 8 years ago

I've noticed the same issue. The longer the normal login takes, the more pronounced the difference is. I had the same thought as you but I would just hash the entered password if the user doesn't exist.

brockallen commented 8 years ago

Well, depends -- do you allow users to sef-register? If so, then they can discover usernames that way. If not, then you can always put a constant time middleware to ensure all login requests always take the same amount of time.

nicholas-brooks commented 8 years ago

@brockallen - No, users do not self-register.

Do you know of any existing constant-time middleware packages? I'd rather use something that is tried and tested than roll my own.

brockallen commented 8 years ago

It'd be something like:

app.Use(async (ctx, next)=>{
    var now = DateTimw.Now;
    await next();
    var diff = DateTime.Now.Subtract(now);
    if (diff < TimeSpan.FromSeconds(5)){
       await Task.Delay(TimeSpan.FromSeconds(5).Subtract(diff));
    }
});
nicholas-brooks commented 8 years ago

@brockallen - Thanks for that. I was thinking along those lines as well, however would need to only do it for certain endpoints (e.g. sign in) and certain verbs.