5

I'm working on a web application along with a web API and I've been warned against what seems to be a basic vulnerability: not checking that the user making an action has sufficient privileges on the resource being accessed. I can't find resources or any best practices.

Here's a scenario:
The URI to access a bank account details is domain.com/details/1234, with 1234 being the user ID. A malicious user can see the URI pattern and try to access domain.com/details/1230. If nothing is done, since he's logged in, he'll see the details for another user.

First, does this kind of vulnerability and related attack have a name? Second, what are the best practices to prevent this? On the web that seems fairly simple, we can simply check the session/ID cookie to compare with the owner of the requested resource. But the API will be used by a mobile app, where cookies are not available. What would be a good way to protect the API?

2 Answers 2

1

To avoid the vulnerability, each request must be authenticated in some way and the authentication verified. This amounts to supplying a session cookie, whether you do it in the GET URL, e.g.

domain.com/details/1234

where 1234 is your user (and also his session), or within a POST or JSON request.

In the above, you have the authentication, but it is not verified. Anyone can claim to be user 1234.

Either you add a separate cookie, which still exposes the user id:

domain.com/details/1234:db81390fb2befd1dd839c37ab39d699cddb8d65b

or you pack everything inside the cookie:

domain.com/db81390fb2befd1dd839c37ab39d699cddb8d65b/details

The above has the advantage that you can internally rewrite the request after checking it to

domain.com/details/1234

so that the application "behind" the security layer can remain unchanged.

The security layer will extract the cookie, verify it is valid (it can contain its own cryptographic signature and a nonce, to avoid replay attacks), and from the cookie-associated session recover the user id 1234 and pass it along.

When authenticating for the first time, a new session is generated and associated to the cookie. If you use a "large enough" cookie, you can add randomization to it:

1. The mobile app requests the user details:

domain.com/db81390fb2befd1dd839c37ab39d699cddb8d65b/details

2. The server destroys cookie db813... and replies with JSON:

{
    'cookie': '926c8a7699c367d3da9370f433189a20b06f8f3d',
    ...other details...
}

3. The next request will have to contain cookie 926c8... to be accepted.

In the above scenario, you can further tighten security by adding state awareness to the application. For example when you receive the above JSON the mobile app is in "Display Details" status, and from that status, only a very limited number of transitions are allowed. You might not be able to transition in one step from there to the "Change User Password" screen, for example.

Which means that if an attacker is able to intercept the JSON request, and attempts to use it to access the Change Password function:

domain.com/926c8a7699c367d3da9370f433189a20b06f8f3d/newpassword

it can be identified as an illegal transition. The newpassword method will "see" that the previous state was not "User Profile" or "Security Menu" but "Display Details", which is not germane, and the connection can then be aborted.

The attacker would then have to first transition from Details to Main Menu and from there to User Profile, thus regenerating the cookie once or twice and thereby cutting out the legitimate user. The legitimate user app does not know that its state is now out of sync and might attempt to use the cookie it has. Such cookie reuse can be detected and taken as evidence that a cookie has been intentionally intercepted. You will not be able to reliably tell who is the attacker and who's the victim, but you can abort both connections.

4

Are you sure that there aren't any cookies available by a mobile app, often this is the case. Also this is known as horizontal privilege escalation. If you can only see details of other users I would also add user enumeration.

If you want to check how these requests are performed you can put a proxy between your phone and the internet (like ZAP or Burp)to see what it actually passes on to the server.

The best practice is to NEVER EVER put session IDs in GET requests. There is a reason why we have cookies and mobile apps support cookies just like any other application. Most mobile banking applications I have seen use a REST API with JSON which doesn't necessarily use cookies (but can although than it's not completely stateless). Often the queries are signed with a type of private key or token.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .