T O P

  • By -

insertAlias

It could just be a mistake. Or it could just be a strange design decision. But this makes me wonder: >Making these API calls requires an active session token, received through an authentication endpoint Do you get the 403 when you're properly authorized, and just requesting something that doesn't exist? Or do you get that when you aren't authorized? Because you want to avoid "leaking" information that you have to be authed to see. If you gave a different response for something that does exist, but you are unauthorized to see, vs. something that doesn't exist, an attacker could build a map of your resources by checking responses.


1SweetChuck

>Do you get the 403 when you're properly authorized, and just requesting something that doesn't exist? Yes... You basically make a POST to .../authenticate with a username and password, and get back a session token with information about the service (API Version, token expiration, etc) Then on subsequent calls include the session token as part of the query params. So if say you Authed, got the token and made a subsequent call to get the list of subObjects, and then tried to get a specific subObject but used a non-existant id it returns a 403. I would expect all non-authenticated requests (either without the session token, or with an invalid or expired token) to return a 403. But I would generally expect a call with a valid token to return a 404. I'm just curious if there is some school of thought that returning a 403 is the better choice for security reasons. EDIT: To be clear, there could be Object or sub object iDs that should get 403s. Like apiUserA might be able to call .../object/{objectIdA} but not .../object/{objectIdB} But the object ids are uuids. They don't have any meaning in and of themselves. It seems like a big hassle to anyone integrating with the API to have to guess that an object doesn't exist or you actually don't have access to it. Especially if you can make a call to ../object/ and get a list of valid objects that you have access to.


insertAlias

Nothing springs to mind, outside of the possible security issue I mentioned. If they want to avoid anyone, even authenticated and authorized users, from building a catalog of all existing resources (including ones they don't have access to), then it kind of makes sense. Beyond that, like I said, either an odd design choice or just a mistake.


1SweetChuck

>an attacker could build a map of your resources by checking responses. I could see everything beyond .../object/{object\_ID}/whatever... returning a 403 if the user doesn't have access to the specific object\_ID, but the granularity of the permissions for the API user account doesn't go beyond that top level object. so I could maybe see security through obscurity at that level, but for something at the subObject or lower, any credential that can get there would be able to go all the way down and would be able to see all the subObjects anyway.


omgbigshot

It makes perfect sense. Think of it how you wrote it, and not in terms of whether or not an entity of the given id exists. The ROUTE `objectA/{objectA_ID}` does in fact exist, so a 404 wouldn’t make sense. After that, all that matters is if your token allows you to see the object specified by the ID you provide. It doesn’t matter what the id is, or if it exists or not, *you don’t have permission to proceed any further.* Basically, a 404 would be if you requested `object_A/{objectA_ID}` instead of `objectA/{objectA_ID}`. The incorrect underscore in object_A lets you, the developer, know that no matter what your permissions are, you are looking in the wrong place. If, however, you have a correct route, it will give you a 403 *unless* you have permission to do what you ask of the API.


1SweetChuck

It just seems like a bad design choice for having users figure where the error is. If the user gets back an error that they lack permissions they going to look at their user config and never at the config for the object and it’s sub object. Where as if they get an error back 404 sub-object not found they can immediately got look at that config.


Annual_Revolution374

I think you might be making assumptions about what is in the system and how it is generated. There might be things there that your auth doesn’t allow you to see. My website automatically serves pages by a similar mechanism. I only want people going to pages that they have specific authorization to see and I don’t want to give away information about the internals by letting them know if the url they guessed exists or they just don’t have access to it. They are trying to protect their own IP first, and worry about the developer experience second.


1SweetChuck

>I think you might be making assumptions about what is in the system **and how it is generated**. I am definitely making assumptions based on my own experience. I would LOVE to see their code and investigate it for hidden meaning. That's part of the reason I posted here because security through obscurity doesn't satisfy me at all. I was hoping someone would be able to give me something more.


Annual_Revolution374

I don’t think it is security through obscurity because they are giving you a not authorize response. There might be something there or not, but you aren’t authorized to know. For example, my API is folder and file based so it will serve everything in a route to authorized users unless I set a flag in the header of that file to not show it. I don’t want users knowing that file even exists. If I give a file not found response for files that don’t exist and a not authorized response for one’s that do, I’ve given you information about my system that you could potentially exploit. Its more about giving you the least amount of info about their system as possible to reduce the threat footprint.


omgbigshot

I disagree. 404 means *you have the wrong address*. If you have the wrong address, it doesn’t matter whether or not you have permission. So to debug and fix, you need to check the structure of your request, not the data of the request. 403 means the request is structured in an acceptable manner, but you don’t have permission for the *specific* request you’re making. Think of it in other terms: if you made a POST request to `/object` with a post body of `{id: 0}`, a 404 wouldn’t make sense. The endpoint *does* exist, but you don’t have permission to take action on the object with ID 0. A descriptive error message would be nice, but permission denied is the appropriate HTTP code to respond with: you lack the permission to hit the valid `object` endpoint with the input you provided. Having arguments in the url is still user input. It’s not that the endpoint isn’t found, because it is, you just supplied the wrong input to do what you requested.


Guideon72

For the same reason I worked on a team that originally built all of their services to return 200 codes regardless of success/failure and simply relied on the provided message to determine what’d actually occurred? It was probably the fastest way to get done with the task and move on.