Closed codewithmecoder closed 9 months ago
Hey @codewithmecoder,
checks for IDOR are trivial, when auto increment IDs are used: simply change the ID and see what is returned.
UUIDs are much harder to predict and hence require much more effort to test and exploit.
Cheers!
Sounds like security by obscurity - it might be better to emphasize that the permission check is the important part, rather than suggesting making it hard to pick an id to test.
True, it does give the feeling. How would the identifier type matter to the permission checks tho?
You pretty much always need the permission checks° - uuids just provide a huge space for an attacker to guess a key within, meaning it'll take an impossibly long time to request every single document by id.
Most apps won't gain much from attackers not being able to guess the id of objects in their system, so paying the costs to wrangle uuids in their api/database might not be worth it.
__ ° except public data, or cases where the uuid grants the permission, like a password reset link, or an invite code and even then you need to "consume" the token so it can't be used over and over again
I think If the application is secure enough and have tracking all the activities of user Increment Id not the insecure reason.
And also consider the memory of using UUID.
What you think? @guest20 , @spekulatius
Yeah, validation of incoming requests (and sanitation of output) are key. Some form of tracking (logging) is good practice for ops.
Same idea with rate limiting as with permission checks... You have to do them anyway as part of other anti-badguy measures (dos and resource conservation when someone scrapes you aggressively).
Implementing rate limits comes with a pile of design questions which need to be answered with a broader view of the system than you'd have when just trying to limit enumeration of a single type of record. Clients might start requesting stuff they don't own or re-requesting cachable resources or even making malformed requests, and all these behaviours need to trigger a limit.
Same idea with rate limiting as with permission checks... You have to do them anyway as part of other anti-badguy measures (dos and resource conservation when someone scrapes you aggressively).
Implementing rate limits comes with a pile of design questions which need to be answered with a broader view of the system than you'd have when just trying to limit enumeration of a single type of record. Clients might start requesting stuff they don't own or re-requesting cachable resources or even making malformed requests, and all these behaviours need to trigger a limit.
Agreed
I have found two benefits of using UUIDs, which aren't easily solved with permission checks / rate limiting:
Permission checks needing context. I offer documents and images over an API. Documents have access checks (e.g. by author), but images need their permission checked via their context (the document they are included in). With incremental IDs, the API can only respond with images side-loaded when requesting the document they are included in, so I can do permission check on the document. With UUIDs I could offer a separate API for images by id and they don't need to be side loaded.
Reducing access because of privacy. The helpdesk has permissions to access all customer's, and search them by email address. However, from a privacy perspective it is not preferable that they can access all without a request from the customer. When using incremental IDs it is easy to fetch data from other customers that you didn't find via an email address search, just by incrementing IDs. When using UUIDs this forces the helpdesk to access customer data only via an email address search.
Both are not water tight solutions. But doing it with IDs takes a lot more work to get somewhat or complete checks.
Further I agree with what others have mentioned; UUIDs have their negative side-effects and permission checks are key for the base.
@lode
Permission checks needing context.
Does the image get a new ID each time it's used in a document?
In a case like that It might make more sense for the image to have one url, and a ?time_limited_access_key=
with base64'ed, signed expire date for the image access
Reducing access because of privacy.
A helpdesk user looking a pile of customers' PII in a row is exactly what a rate limit is for though. You ... what to limit... the rate they trawl through customers.
Helpdeskers are a particular situation for sure, and you're going to need to have a nice, detailed the audit log when you come to the conversation with their manager and the HR person.
Does the image get a new ID each time it's used in a document?
No.
A helpdesk user looking a pile of customers' PII in a row is exactly what a rate limit is for though. You ... what to limit... the rate they trawl through customers.
That's something to add as well, but it doesn't work very well for this use case. Staff has quite unlimited time if they want to iterate over ids, so it is relatively easy to stay under the radar of rate limiting.
Helpdeskers are a particular situation for sure, and you're going to need to have a nice, detailed the audit log when you come to the conversation with their manager and the HR person.
Also indeed something to add. But it is more a law-based requirement than an actual protection, as I've found it common that no-one is actually looking at the audit-log. So some additional checks to prevent misuse are welcome.
@lode I think we're down at the level of specifics that don't really fit into a high level best practices document for API security. The only reason I mentioned an audit log is so the org knows who to Cc when they're sending out the "we take your security seriously however unfortunately ..." email.
Of course.
My main argument is that I experienced that there are valid reasons to go for UUIDs, which aren't easily circumvented by other measures. Going into those details is for sure not something to write down in the repo.
That said, if you just need a number from a large key space base64'ing 64 bytes from /dev/random is just as difficult for an attacker to guess.
What is the pros and cons for these two identity?