🔐 OWASP API Security Training

Understanding API3:2023 - Excessive Data Exposure

📚 Introduction to Excessive Data Exposure

Welcome to this comprehensive guide on one of the most critical OWASP API security vulnerabilities: Excessive Data Exposure. This vulnerability occurs when an API returns more information than necessary, relying on the client-side application to filter sensitive data before displaying it to users.

⚠️ Why This Matters

Even if the User Interface (UI) doesn't display sensitive information, if the API sends it in the response, attackers can intercept this data through man-in-the-middle attacks, network sniffing, or by examining API responses directly through browser developer tools or proxy tools.

🎯 The Vulnerability Explained

Scenario: Credit Card Information Disclosure

Consider a banking application where users want to view their credit card details. The UI is designed to show:

  • Credit Card Number (partially masked: **** **** **** 1234)
  • Cardholder Name
  • Expiration Date

However, the API response also includes the CVV/CVC (Card Verification Value), which should NEVER be transmitted or stored after the initial transaction authorization.

📊 Visual Representation of the Attack

User/Browser UI Application (Filters Data) API Server (Returns All Data) Database Attacker (MITM) Request API Call Query Full Response (includes CVV!) Filtered View (CVV hidden) Intercepts Full Response!

💻 Example: Vulnerable API Response

❌ VULNERABLE: API Returns Excessive Data

When a user requests their credit card information, the API endpoint returns:

GET /api/v1/user/creditcard
{ "status": "success", "data": { "cardNumber": "4532 1234 5678 9010", "cardholderName": "John Doe", "expirationDate": "12/2026", "cvv": "123", ← SENSITIVE DATA EXPOSED! "cardType": "Visa", "issuingBank": "Example Bank", "creditLimit": 5000, ← UNNECESSARY DATA "currentBalance": 1250, ← UNNECESSARY DATA "billingAddress": { "street": "123 Main St", "city": "New York", "zipCode": "10001" } } }
✅ SECURE: API Returns Only Required Data

The secure implementation returns only what the UI needs to display:

GET /api/v1/user/creditcard/display
{ "status": "success", "data": { "cardNumberMasked": "**** **** **** 9010", "cardholderName": "John Doe", "expirationDate": "12/2026", "cardType": "Visa" } }

🔍 How Attackers Exploit This Vulnerability

Attack Methods

  • Man-in-the-Middle (MITM) Attacks: Intercepting network traffic between client and server
  • Browser Developer Tools: Examining network responses in the browser console
  • Proxy Tools: Using tools like Burp Suite, OWASP ZAP, or mitmproxy to capture API responses
  • Mobile App Reverse Engineering: Decompiling mobile apps to view API calls
  • Session Hijacking: Stealing session tokens to replay API requests

🛠️ Testing for Excessive Data Exposure

Step 1: Capture API Traffic

Use a proxy tool to intercept API requests and responses:

burpsuite &
Configure browser to use proxy: localhost:8080
Browse to the application and perform actions

Step 2: Analyze API Responses

Look for sensitive data in API responses that isn't displayed in the UI:

Look for: passwords, tokens, CVV, SSN, private keys, internal IDs
Compare API response with what's displayed in the UI
Check for admin-only fields returned to regular users

Step 3: Test with curl Command

Make direct API calls to examine the response:

curl -X GET "https://api.example.com/v1/user/profile" -H "Authorization: Bearer YOUR_TOKEN" -v

Step 4: Using Browser Developer Tools

Open Chrome/Firefox Developer Tools (F12)
Navigate to Network tab
Filter by XHR/Fetch requests
Click on API calls and examine Response tab

Step 5: Automated Testing with OWASP ZAP

zap.sh -daemon -port 8090
Configure ZAP as proxy in browser
Browse application normally
Run active scan on captured requests
Review alerts for sensitive data exposure

🛡️ Prevention Best Practices

Practice Description Implementation
Schema-Based Response Filtering Define explicit schemas for API responses Use JSON Schema or OpenAPI specifications
Data Transfer Objects (DTOs) Create specific objects for API responses Map database models to DTOs with only required fields
Field-Level Authorization Check permissions for each field returned Implement role-based field filtering
API Response Review Regularly audit API responses Use automated tools and manual code reviews
Minimize Data Collection Don't store data you don't need Follow data minimization principles

💡 Code Examples

Python/Flask - Secure Implementation
from flask import Flask, jsonify from flask_login import current_user class CreditCardDTO: def __init__(self, card): self.card_number_masked = self.mask_card(card.number) self.cardholder_name = card.holder_name self.expiration_date = card.expiration_date self.card_type = card.card_type # CVV is NEVER included in response def mask_card(self, number): return "**** **** **** " + number[-4:] def to_dict(self): return { "cardNumberMasked": self.card_number_masked, "cardholderName": self.cardholder_name, "expirationDate": self.expiration_date, "cardType": self.card_type } @app.route('/api/v1/user/creditcard') @login_required def get_credit_card(): card = db.query(CreditCard).filter_by(user_id=current_user.id).first() card_dto = CreditCardDTO(card) return jsonify(card_dto.to_dict())
Node.js/Express - Secure Implementation
const express = require('express'); const router = express.Router(); // Define allowed fields for response const ALLOWED_FIELDS = [ 'cardNumberMasked', 'cardholderName', 'expirationDate', 'cardType' ]; function maskCardNumber(cardNumber) { return '**** **** **** ' + cardNumber.slice(-4); } function filterCardData(card) { return { cardNumberMasked: maskCardNumber(card.number), cardholderName: card.holderName, expirationDate: card.expirationDate, cardType: card.type // CVV is intentionally excluded }; } router.get('/api/v1/user/creditcard', authenticateUser, async (req, res) => { try { const card = await CreditCard.findOne({ userId: req.user.id }); const safeCardData = filterCardData(card); res.json({ status: 'success', data: safeCardData }); } catch (error) { res.status(500).json({ status: 'error', message: 'Server error' }); } });

🔐 Security Checklist

✓ Implementation Checklist

  • ☑ Never return sensitive fields like passwords, CVV, SSN in API responses
  • ☑ Use DTOs (Data Transfer Objects) to control response structure
  • ☑ Implement field-level authorization checks
  • ☑ Document which fields each endpoint should return
  • ☑ Use API response schemas (OpenAPI/Swagger)
  • ☑ Regularly audit API responses for unnecessary data
  • ☑ Implement proper logging without exposing sensitive data
  • ☑ Use HTTPS/TLS for all API communications
  • ☑ Implement rate limiting to prevent mass data extraction
  • ☑ Conduct regular penetration testing

📈 Real-World Impact

Case Study: Data Breach Scenario

A financial technology company exposed full user profile data including Social Security Numbers, bank account details, and authentication tokens through their mobile API. While their mobile app only displayed basic information, attackers used network interception tools to capture the full API responses, leading to:

  • 500,000+ user accounts compromised
  • $12 million in fraud losses
  • Regulatory fines of $5 million (GDPR/PCI-DSS violations)
  • Severe reputation damage and loss of customer trust

🎓 Key Takeaways

  • Never trust the client: Don't rely on UI to filter sensitive data
  • API responses are visible: Assume all API responses can be intercepted
  • Implement server-side filtering: Only send data the client needs to see
  • Follow principle of least privilege: Return minimum required data
  • Regular security audits: Continuously review API responses

🔗 Additional Resources

  • OWASP API Security Top 10: https://owasp.org/www-project-api-security/
  • OWASP Testing Guide: API Testing section
  • Tools: Burp Suite, OWASP ZAP, Postman, curl
  • Standards: OpenAPI Specification, JSON Schema