DEV Community

RESTful Security: Plug the Leaks!

C. Dylan Shearer on April 07, 2018

TL;DR: Don't leak information through HTTP error codes. Here is a possible vulnerability that is probably not very serious but easy to overlook. ...
Collapse
 
sokolovdenis profile image
Denis Sokolov

Maybe "more RESTFully" logic may be:
return 401 if user unauthenticated (it's does not matter exists account or not);
return 403 if user authenticated but is not owner of requested account (it's does not matter exists account or not);
return 404... I think never :)

Collapse
 
sqlrob profile image
Robert Myers

That has the exact same problem as 401 / 404, it just requires the the additional step of registering. There is little to no security gain.

Collapse
 
sokolovdenis profile image
Denis Sokolov

If there is no authentication in API, and we want to protect our growth rate statistics - yes, same problem exists. And GUID instead of INT identifiers may help.

Thread Thread
 
sqlrob profile image
Robert Myers

Even if there is authentication in API, it doesn't matter. (See Panera's "fix")

GUID or other unpredictable identifier is the only real fix. Rate limiting each user can help as well, but how useful that is really depends on how hard it is to get authentication tokens.

Collapse
 
dshearer profile image
C. Dylan Shearer

That certainly makes sense.

Collapse
 
rhymes profile image
rhymes

Agreed, also don't use internal db ids in the api so the attacker cannot infer the sequencing

Collapse
 
neilmadden profile image
Neil Madden

If your external ids are unguessable (e.g., 256-bit random strings) then this attack completely disappears. Another alternative is to only expose /api/accounts/me if there is no valid reason for a user to ever access any other account.

Collapse
 
danidee10 profile image
Osaetin Daniel

Yep.It's always good to use a random string or a different Identifier for any public resource.

Collapse
 
jonerer profile image
Jon Mårdsjö • Edited

Not to say this is not important, but there is more to it if you want to plug the informational leaks in a serious way.

Using the same example as in the OP, let's say example.com/api/accounts/300 and 301 both return the same HTTP code. Another thing to think about then is timing -- let's say an attacker can do a thousand requests for each of the accounts.

If they find that on average accounts 301, 302 and 304 take 10ms, but 300, 303 and 305 take 8.5ms -- then they have found that there's a difference. Perhaps the backend code is written so that if you find that the account exists, you do a credentials check; but if the account doesn't exist you skip the credentials check. Then an attacker can still know whether the account exists or not, given the timings.

Collapse
 
jonerer profile image
Jon Mårdsjö

Btw this is also the reason why checking an auth token with == is not a valid practice -- you have to use a "time-secure" comparison

Collapse
 
mattcanello profile image
Mateus Canello Ottoni

I wrote an article about building better web APIs and I pointed out that I use a similar approach: return 404 not only when the resource does not exist, but also when it does exist and the authenticated user doesn't own it.