Open yaronyg opened 8 years ago
What I do is I use a library called scrypt, it takes a parameter of maxtime. it is intentionally designed to take a long time to evaluate the comparison. This has a number of advantages the main advantage is that brute force attacks take too long to evaluate and if the database is compromised the secret is kept safe.
node-scrypt is the library I use, if your not comfortable with using a newer cryptographic library you could go with the more well known bcrypt.
The problem here is that we have to validate the admin password on each and every request. Now to be we could apply an optimization where we validate once per connection but that makes me nervous. In any case I don't think this is a huge deal to solve it's just a priority issue that we haven't solved it yet.
You could do what oauth2 does and use a password exchange for a token, then use the token for successive requests.
Yeah but that is a lot of complexity. My suspicion is that a simpler solution is to just put an object on req.connection that indicates if the connection has been authenticated or not. If the connection hasn't been authenticated then we run a constant time check. If it has, then we don't need to do anything.
Sounds similar to a session pattern
Not exactly. The session pattern, if done right, isn't tied to a specific TCP connection. Rather it establishes a session as an in memory object that can be accessed across multiple connections. The reason for this is that HTTP requests are typically sprayed across multiple connections which can themselves be re-mixed inside of a proxy. This means that the server infrastructure cannot know ahead of time which connection a request for a particular client will come in on and so even with request pinning it typically makes sense to manage the session above the TCP layer.
In our case however we know that all connections will come directly from the client to the same instance of the server without any proxy in between so we can afford to associate security with the connection.
Right now we secure the connection between the webview and Express-PouchDB using a secret sent in the clear over HTTP on localhost. Eventually the connection will be encrypted but in the meantime the real problem is a timing attack.
Imagine that bad client A connects to good Express-PouchDB server B on the mobile device. A doesn't know the authorization password. But what A can do is send a fake password starting with some binary value. Then by timing how long it takes for the Express-PouchDB server to return an error response it is in theory possible for the attacker to figure out how many characters into the fake password the string compare got before failing. This would allow the attacker to just try repeated authorization attempts in order to figure out the password.
I can't prove that this attack is workable in practice but it seems like the kind of thing we should protect again.
The first defense is to make sure that we use a constant time compare when validating the authorization header.
The second defense, which is trickier, is to throttle how many compares we do. But we have to be careful or we would throttle the white hats along with the black hats. So we would need to do throttling on a per TCP connection and not a blind per HTTP request basis.