-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Constant time to protect against timing attacks #20
Conversation
upstream has been fixed; length of the password is now not leaked anymore. |
Fixes leaking of whether username is correct.
app.use(basicAuth( { authorizer: myAuthorizer } )) | ||
|
||
function myAuthorizer(username, password) { | ||
return compare("admin", username) & compare("admin-password", password); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like there's a typo in this code. I believe @hraban meant a &&
return compare("admin", username) & compare("admin-password", password); | |
return compare("admin", username) && compare("admin-password", password); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially made the same mistake, but someone pointed out to me that using a short-circuiting conjunction operator (&&
) will leak information about the username. Using an eager operator (&
) will be actually constant time.
I added a comment to the readme to elaborate on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤦♂️
yes let's document to prevent same mistakes in the future! ;-)
hello all, any update on this? is there anything in the way of this getting merged? |
@LionC is there anything specific blocking this PR? Anything I can do to help it getting merged? It's a bit of a security issue at the moment, and anyone using this module with a standard comparator is at risk. Would be lovely to get this one step closer to merging, for the greater good :) |
Hi @hraban, thanks for pinging me again about this! I had a lot on my mind the last months, keeping me from doing the typescript rewrite, which I planned to include your proposal into. As I do not know how much time I will have the next weeks, I will look into your proposal until this Sunday and make sure, that we change the comparison to be constant time instead. |
hope you're fine and healthy! best of luck with whatever's bugging you. if you're going to rewrite in typescript you won't be able to use the // explicit full comparison to avoid leaking data about username
let ok = true;
ok = safeCompare(username, credentials.name) && ok;
ok = safeCompare(password, credentials.pass) && ok;
return ok; I guess it's more readable, in the end. |
It is always possible to force TypeScript compiling a bitwise operation on non-numbers by forcefully disabling the type checker with // @ts-ignore
const bitwise = true & true; |
Fair enough :D |
yes, the safe-compare dependency is essentially a passthrough for that crypto operation if it exists, otherwise a shim for older node versions. it helps support node releases <6.6.0, probably not a very large part of node installations out there anymore? |
@hraban as node 6 support ends this month, I decided not to include the dependency. I also decided to provide the time safe compare method from the module. As that would heavily deviate from the code in this PR, I decided to do a new branch to implement all of this and opened a new PR. I made sure to add credits to you and the original author of the safe comparison algorithm. |
Using native string compare for passwords (even when hashed) exposes you to timing attacks. Using a constant time string compare protects against this.