Mass Assignment with Bearer Tokens
How Mass Assignment Manifests in Bearer Tokens
Mass assignment vulnerabilities in Bearer Token implementations occur when applications automatically bind incoming token claims to server-side objects without proper validation. This creates attack vectors where malicious actors can manipulate token claims to escalate privileges or access unauthorized data.
The most common manifestation involves scope claims. Consider a JWT token with a scope field that determines user permissions. An attacker might modify the token to include additional scopes like 'admin' or 'write' that they shouldn't possess:
// Malicious token manipulation
// Original: { "scope": "read" }
// Modified: { "scope": "read admin write" }
Another pattern involves role claims in Bearer Tokens. When applications deserialize token claims directly into user objects, attackers can inject arbitrary role assignments:
// Vulnerable deserialization
const claims = jwt.verify(token, secret);
const user = {
id: claims.sub,
role: claims.role || 'user', // Direct assignment without validation
permissions: claims.permissions || []
};
Property-based mass assignment occurs when tokens contain nested objects that map directly to database entities. An attacker might craft a token with additional properties that get assigned to database records:
// Attack scenario
// Token contains: { "user": { "id": 123, "role": "admin" } }
// Server blindly assigns: user.role = 'admin'
Role-based access control (RBAC) systems are particularly vulnerable when they rely on token claims for authorization decisions. A token claiming elevated privileges bypasses normal authentication checks:
// Vulnerable RBAC check
const claims = jwt.verify(token, secret);
if (claims.role === 'admin') {
return adminDashboard(); // No additional verification
}
Database query parameter injection through token claims represents another attack vector. When token claims directly influence query parameters without sanitization:
// Vulnerable query construction
const claims = jwt.verify(token, secret);
const query = `SELECT * FROM users WHERE org_id = ${claims.org_id}`;
// Attacker modifies org_id to access other organizations
Bearer Tokens-Specific Detection
Detecting mass assignment vulnerabilities in Bearer Token implementations requires systematic testing of token claim handling. Start by examining how your application processes token claims during authentication and authorization.
Manual testing involves modifying token claims and observing system behavior. Use tools like jwt.io or PyJWT to decode and modify tokens:
# Test script for scope manipulation
import jwt
import requests
# Original token
original = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
# Decode and modify
header, payload, _ = original.split('.')
payload_data = json.loads(base64.b64decode(payload + '=='))
payload_data['scope'] += ' admin write delete'
# Re-encode
modified_token = jwt.encode(
payload_data,
'your-secret-key',
algorithm='HS256'
)
# Test modified token
response = requests.get(
'https://api.example.com/protected',
headers={'Authorization': f'Bearer {modified_token}'}
)
print(response.status_code, response.json())
middleBrick provides automated detection for Bearer Token mass assignment vulnerabilities through its comprehensive scanning capabilities. The scanner identifies insecure claim handling patterns across 12 security categories, including authentication bypasses and privilege escalation attempts.
Key detection patterns include:
- Unvalidated scope claims that allow privilege escalation
- Direct assignment of token claims to database entities
- Insecure role-based access control implementations
- Missing claim validation for critical properties
- Database query construction using raw token claims
The scanner tests for 27 regex patterns related to system prompt leakage and prompt injection, which can reveal how token claims are processed and whether they're properly sanitized.
middleBrick's OpenAPI/Swagger analysis cross-references token claim definitions with runtime behavior, identifying mismatches between documented security requirements and actual implementation.
Bearer Tokens-Specific Remediation
Remediating mass assignment vulnerabilities in Bearer Token implementations requires a defense-in-depth approach. The foundation is strict claim validation and whitelisting.
Implement claim whitelisting to prevent unauthorized properties:
// Whitelist approach for JWT claims
const allowedClaims = ['sub', 'email', 'scope', 'exp', 'iat'];
function validateClaims(tokenClaims) {
const validated = {};
for (const claim of allowedClaims) {
if (claim in tokenClaims) {
validated[claim] = tokenClaims[claim];
}
}
return validated;
}
// Usage
const claims = validateClaims(jwt.verify(token, secret));
Role-based access control should use server-side verification rather than token claims:
// Server-side RBAC verification
class AuthService {
async verifyAdmin(token) {
const claims = jwt.verify(token, secret);
const user = await db.users.findOne({ id: claims.sub });
if (!user || user.role !== 'admin') {
throw new Error('Unauthorized');
}
return user;
}
}
Scope validation requires strict parsing and verification:
// Secure scope validation
const allowedScopes = ['read', 'write', 'delete'];
function validateScope(token, requiredScope) {
const claims = jwt.verify(token, secret);
const tokenScopes = claims.scope?.split(' ') || [];
// Check if required scope is authorized
if (!tokenScopes.includes(requiredScope)) {
throw new Error('Insufficient scope');
}
// Verify no unauthorized scopes
const unauthorized = tokenScopes.filter(
scope => !allowedScopes.includes(scope)
);
if (unauthorized.length > 0) {
throw new Error('Invalid scopes detected');
}
}
Database operations should never use raw token claims:
// Secure database access
async function getUserData(token, userId) {
const claims = jwt.verify(token, secret);
const user = await db.users.findOne({
id: userId,
org_id: claims.org_id // Verify organization match
});
if (!user) {
throw new Error('Unauthorized');
}
return user;
}
Input validation libraries can help enforce claim constraints:
// Using Joi for claim validation
const Joi = require('joi');
const claimSchema = Joi.object({
sub: Joi.string().required(),
email: Joi.string().email(),
scope: Joi.string().pattern(/^[a-zA-Z0-9 ]+$/),
exp: Joi.number().required()
});
function validateTokenClaims(claims) {
const { error } = claimSchema.validate(claims);
if (error) {
throw new Error(`Invalid token claims: ${error.message}`);
}
}
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |