Back to Cheat Sheets

๐Ÿ”’ Broken Object Property Level Authorization

OWASP API Security Top 10 - API03

HIGH RISK

๐Ÿ“‹ What Is It?

Broken Object Property Level Authorization occurs when APIs expose too many object properties or allow modification of restricted properties. This manifests as Excessive Data Exposure (seeing sensitive fields) and Mass Assignment (modifying restricted fields).

API03 OWASP Rank
Object Property Level
2 Types Exposure+Assignment

โš ๏ธ Common Exploits

  • Excessive Data Exposure: API returns password_hash, SSN, salary in user profile
  • Mass Assignment: Set is_admin=true in profile update request
  • Price Manipulation: Change product price or discount in order request
  • Role Escalation: Modify role field to gain admin privileges
  • Status Manipulation: Change order status from pending to approved
  • Hidden Fields: Sensitive fields exposed in API but hidden in UI

๐Ÿ”ด Attack Flow

1. User requests profile: GET /api/users/me
โ†“
2. API returns ALL fields including sensitive ones
โ†“
3. Attacker observes is_admin: false
โ†“
4. Sends PUT with is_admin: true
โ†“
5. BREACH: Admin access granted!

โŒ Vulnerable Code

// Bad: Returns entire model with sensitive fields @app.route('/api/users/me') @login_required def get_profile(): # Returns ALL fields including sensitive ones! return jsonify(current_user) // Response exposes: { "id": 123, "name": "John Doe", "password_hash": "$2b$12$...", โ† Shouldn't expose! "is_admin": false, โ† Shouldn't expose! "salary": 85000, โ† Shouldn't expose! "ssn": "123-45-6789" โ† Shouldn't expose! } // Bad: Mass assignment vulnerability @app.route('/api/users/<user_id>', methods=['PUT']) @login_required def update_profile(user_id): user = User.query.get(user_id) # Accepts ALL fields from request! user.update(**request.json) โ† DANGEROUS! db.session.commit() return jsonify(user)

โœ… Secure Code

// Good: Whitelist fields to return @app.route('/api/users/me') @login_required def get_profile(): # Only return safe fields return jsonify({ 'id': current_user.id, 'name': current_user.name, 'email': current_user.email, 'created_at': current_user.created_at }) // Good: Use DTO/serializer for responses class UserSerializer: safe_fields = ['id', 'name', 'email'] def serialize(user): return {field: getattr(user, field) for field in safe_fields} // Good: Whitelist fields for updates @app.route('/api/users/<user_id>', methods=['PUT']) @login_required def update_profile(user_id): user = User.query.get_or_404(user_id) # Only allow specific fields to be updated allowed_fields = ['name', 'email', 'bio'] for field in allowed_fields: if field in request.json: setattr(user, field, request.json[field]) db.session.commit() return jsonify(UserSerializer.serialize(user))

โœ“ Prevention Checklist

  • Use DTOs/serializers to control exposed fields
  • Whitelist fields for API responses
  • Whitelist fields accepted in updates
  • Never return entire database models
  • Remove sensitive fields: passwords, tokens, keys
  • Implement role-based field visibility
  • Validate field permissions on every request
  • Use separate models for input/output
  • Test with different user roles
  • Code review for property exposure

๐Ÿ” Detection & Tools

Testing Tools:

Burp Suite OWASP ZAP Postman curl Fiddler

Prevention Libraries:

Marshmallow Django REST Framework Pydantic Jackson (Java) Active Model Serializers

How to Test:

  • Examine all API response fields for sensitive data
  • Try adding admin/privileged fields in PUT/PATCH
  • Test mass assignment with unexpected fields
  • Compare database schema vs API response
  • Check for password hashes, tokens in responses

๐ŸŒ Real-World Breaches

  • LinkedIn (2012): Mass assignment allowed users to modify any profile field
  • GitHub (2012): Mass assignment vulnerability allowed public key injection
  • Ruby on Rails Apps: Mass assignment vulnerabilities in early Rails versions
  • E-commerce Platforms: Price manipulation via mass assignment in checkout APIs
  • Banking APIs: Excessive data exposure revealing account balances and PINs

๐Ÿ“Œ Quick Tips

  • DO NOT return entire database models
  • DO NOT accept all request fields blindly
  • DO NOT expose admin/internal fields
  • DO use serializers/DTOs for responses
  • DO whitelist allowed update fields
  • DO implement field-level permissions

๐Ÿ“œ Compliance

Related Standards:

  • GDPR Art. 5 - Data Minimization
  • PCI-DSS Requirement 3.3
  • HIPAA ยง164.514 - De-identification
  • SOC 2 CC6.1
  • ISO 27001 A.9.4
  • CCPA Data Minimization