# Mass Parameter Assignment

## Overview

Many modern software development frameworks bind user input directly into internal objects. This is known as mass parameter assignment or auto-binding. While this feature is helpful to assign parameters to objects, an attacker can use it to write fields that should not be set by a user, leading to privilege escalation, data tampering, bypass of security mechanisms, and more.

For example, consider a Java Spring web application with a `User` object:

```java
public class User {
    private String username;
    private String password;
    private String email;
    private boolean isAdmin;

    // Getters & Setters
}
```

The web application implements the following view:

```html
<form action="/createUser" method="POST">
    <input name="username" type="text">
    <input name="password" type="text">
    <input name="email" text="text">
    <input type="submit" value="Create">
</form>
```

The controller that handles the creation request (Spring provides the automatic bind with the `User` model):

```java
@RequestMapping(value = "/createUser", method = RequestMethod.POST)
public String createUser(User user) {
    userService.add(user);
    return "successPage";
}
```

In this case, the browser sends the following request when the form is submitted:

```
POST /createUser HTTP/1.1
...

username=bob&password=supersecretpassword&email=bob@domain.test
```

Due to the auto-binding, an attacker can add the `isAdmin` parameter to the request, which the controller will automatically bind to the model. As a result, the request below will create a user with administrative privileges.

```
POST /createUser HTTP/1.1
...

username=bob&password=supersecretpassword&email=bob@domain.test&isAdmin=true
```

This page contains recommendations for the implementation of protection against mass parameter assignment attacks.

## General

<div align="left"><img src="/files/QJuMWI21M60ZKzo0mFAN" alt=""></div>

* Use Data Transfer Objects instead of binding parameters directly to internal objects.

<details>

<summary>Clarification</summary>

A Data Transfer Object (DTO) is an object which only contains attributes that can be modified by a user. It serves as an intermediary between received parameters and a final object. Using Data Transfer Objects makes mass parameter assignment or auto-binding completely safe because they do not contain additional parameters that should not be passed by a user.

For example, the `UserRegistrationFormDTO` below does not contain the `isAdmin` parameter that might be used to elevate privileges as it is described in the [Overview](#overview) section:

```java
public class UserRegistrationFormDTO {
    private String userid;
    private String password;
    private String email;

    // NOTE: isAdmin field is not present

    // Getters & Setters
}
```

</details>

* If there is no possibility to use DTOs, use an allow list and non-sensitive parameters to restrict auto-binding only to those. Avoid using block lists.

<details>

<summary>Example</summary>

In the example below, the binding function uses a set of allowed fields, restricting any other field to be auto-bound and preventing the mass parameter assignment attack.

```java
@Controller
public class UserController
{
    @InitBinder
    public void initBinder(WebDataBinder binder, WebRequest request) {
        binder.setAllowedFields(["userid", "password", "email"]);
    }
    // ...
}
```

</details>

* Implement comprehensive input validation for each request parameter, see the [Input Validation](/application-security-handbook/web-application/input-validation.md) page.

## Auto-binding allow list implementation

{% tabs %}
{% tab title="Go: Gin" %}
[Gin Web Framework](https://github.com/gin-gonic/gin) allows mass parameter assignment with functions such as `Bind()`, `shouldBind()` or `mustBind()`. These functions rely on the `form:` tag in a struct and only attributes tagged with `form:` will be considered safe for auto-binding. Use the `form` tag to mark parameters that are safe to be auto-bound.

For example, the `User` struct below does not have the `form:` tag for the `IsAdmin` parameter. It means that `IsAdmin` can not be auto-bound and used to elevate privileges as it is described in the [Overview](#overview) section:

```go
package main

import (
    "log"
    "github.com/gin-gonic/gin"
)

type User struct {
    Username    string  `form:"username"`
    Password    string  `form:"password"`
    Email       string  `form:"email"`
    IsAdmin     bool    `default:false`
}

func main() {
    route := gin.Default()
    route.POST("/createUser", createUser)
    route.Run()
}

func createUser(c *gin.Context) {
    var user User
    if c.ShouldBind(&user) == nil {
        log.Println(user.Username)
        log.Println(user.Password)
        log.Println(user.Email)
        log.Println(user.IsAdmin)
    }
    c.String(200, "Success")
}
```

{% endtab %}
{% endtabs %}

## References

* [OWASP Cheat Sheet Series: Mass Assignment Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xn3va.gitbook.io/application-security-handbook/web-application/vulnerability-mitigation/mass-parameter-assignment.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
