Post

3. Mass assignment vulnerabilities

Mass assignment vulnerabilities

Mass assignment, aka auto-binding, can inadvertently create hidden parameters. It occurs when software frameworks automatically bind request parameters to fields on an internal object. Auto-binding may therefore result in the app supporting parameters that were never intended to be processed by the developer.

Identifying hidden parameters

Since auto-binding creates params from object fields, we can often identify these by manually examining objects returned by the API. For example, consider a PATCH /api/users/ request, which enables users to update their username and email, and includes the following JSON:

1
2
3
4
{
    "username": "wiener",
    "email": "wiener@example.com",
}

A concurrent GET /api/users/123 request returns the following JSON:

1
2
3
4
5
6
{
    "id": 123,
    "name": "John Doe",
    "email": "john@example.com",
    "isAdmin": "false",
}

This may indicate that the hidden id and isAdmin params are bound to the internal user object, alongside the updated username and email params.

Testing auto-binding vulnerabilities

We can test if we can modify the enumerated isAdmin param value by adding it to the PATCH request:

1
2
3
4
5
{
    "username": "wiener",
    "email": "wiener@example.com",
    "isAdmin": false,
}

In addition, we can send a PATCH request with an invalid isAdmin param value:

1
2
3
4
5
{
    "username": "wiener",
    "email": "wiener@example.com",
    "isAdmin": "foo",
}

If the app behaves differently, this may suggest that the invalid value impacts the query logic, but the valid value does not, which in turn, may indicate that the parm can be successfully updated by the user. We can send the PATCH request with isAdmin param value set to true, to try and exploit the vulnerability:

1
2
3
4
5
{
    "username": "wiener",
    "email": "wiener@example.com",
    "isAdmin": true,
}

If the isAdmin value in the request is bound to the user object without adequate validation and sanitization, the user wiener may be incorrectly granted admin privileges. To determine if this is the case, we can browse the app as wiener to see whether we can access admin functionality.

Lab: Exploiting a mass assignment vulnerability

Objective: To solve the lab, find and exploit a mass assignment vulnerability to buy a Lightweight l33t Leather Jacket. You can log in to your own account using the following credentials: wiener:peter.

  1. When we log in as wiener we can see the item’s initial price:

  2. If we add the jacket to our cart, go to checkout and place our order, we will notice that there is both a GET and a POST request to the /api/checkout endpoint:

  3. The response to the GET request and the POST request itself have a similar parameter structure, but the former includes some additional parameters:

  4. In the GET request’s response there is a parameter called chosen_discount which includes a percentage value, but on the POST request there isn’t. Thus, we can add it manually and set its value to 100:

Preventing vulnerabilities in APIs

When designing APIs, we must make sure that security is a consideration from the beginning:

  • Secure your documentation if we don’t intend our API to be publicly accessible.
  • Ensure our documentation is kept up to date so the legitimate testers have full visibility of the API’s attack surface.
  • Apply an allowlist of permitted HTTP methods.
  • Validate that the content type is expected for each request or response.
  • Use generic error messages to avoid giving away info that may be useful for an attacker.
  • Use protective measures on all API version, not just the current production one.

To prevent auto-binding vulnerabilities, we can allowlist the properties that can be updated by the user, and blocklist sensitive properties that should not be updated by the user.

Resources

This post is licensed under CC BY 4.0 by the author.