Friday evening. Security team gets an alert: unusual traffic pattern on API. Analysis shows: attacker found endpoint /api/users/{id} which returns data for any user by ID. Iterating through millions of IDs, scraping the full user database. BOLA (Broken Object Level Authorization) - endpoint doesn’t check if the requesting user has the right to see that specific user’s data.
Data of 3 million users leaked. GDPR breach notification. Fine, reputation, lawsuits. And all it needed was one check: “does user X have the right to object Y?”
API is everywhere. Mobile apps communicate with backend via API. Single Page Applications - via API. Microservices - API. Third-party integrations - API. IoT devices - API. API is the main attack surface of modern applications. And often the least protected.
Why is API security harder than traditional web security?
APIs don’t have a “login page”. Traditional web app: there’s a login form, there’s a session, there are cookies. API: bearer token, API key, JWT - different mechanisms, different vulnerabilities.
Machine-to-machine communication. APIs often serve other systems, not people. Harder to apply traditional anti-automation measures (CAPTCHA).
Scale and velocity. API handles thousands of requests per second. Attacks can be subtle - not DDoS, but slow data extraction over months.
Documentation as attack surface. OpenAPI/Swagger specs are public. Attacker knows exactly what endpoints exist, what parameters they accept.
Business logic exposure. API exposes business logic directly. Web app can hide logic behind UI - API has no such layer.
Multiple consumers. One API serves: mobile app, web app, third-party integrations, internal services. Each has different security needs.
What are the most important threats according to OWASP API Top 10?
API1: Broken Object Level Authorization (BOLA) - API doesn’t check if user has the right to a specific object. /api/orders/123 - can user see order 123, or only their own?
API2: Broken Authentication - weak authentication mechanisms: weak tokens, no expiration, credential stuffing vulnerability.
API3: Broken Object Property Level Authorization - user can see object but not all its fields, or can modify fields they shouldn’t.
API4: Unrestricted Resource Consumption - no limits: rate limiting, payload size, query complexity. Leads to DoS, excessive costs.
API5: Broken Function Level Authorization - user calls admin functions (/api/admin/delete-user) not meant for them.
API6: Unrestricted Access to Sensitive Business Flows - automation of business operations (mass ticket buying, credential stuffing, scraping).
API7: Server Side Request Forgery (SSRF) - API accepts URL from user and makes request - attacker can scan internal network.
API8: Security Misconfiguration - default configs, verbose errors, unnecessary HTTP methods, missing security headers.
API9: Improper Inventory Management - old API versions still accessible, undocumented endpoints, deprecated features not disabled.
API10: Unsafe Consumption of APIs - your API consumes third-party APIs without proper validation - supply chain risk.
How to implement proper authentication for API?
OAuth 2.0 + OpenID Connect. Standard for delegated authorization and authentication. Use proven implementations (Auth0, Okta, Keycloak), don’t roll your own.
JWT (JSON Web Tokens) best practices:
- Use strong signing algorithm (RS256 > HS256 for public clients)
- Short expiration times (15 min access token + refresh token flow)
- Validate signature, expiration, issuer, audience
- Store signing keys securely (HSM, KMS)
- Consider token binding / proof of possession
API Keys - when to use:
- Service-to-service authentication (server-side only)
- Identify calling application (not user)
- Always over HTTPS
- Rotate regularly
- Scope and rate limit per key
Don’t do:
- Basic auth (unless over HTTPS and for legacy support)
- Custom token schemes without crypto expertise
- Long-lived tokens without refresh mechanism
- Tokens in URLs (logged, cached, leaked in referrers)
Multi-factor for sensitive operations. Token gives access, but for DELETE /api/account require additional verification.
How to implement authorization at object and function level?
Object Level Authorization (vs. BOLA):
# Bad - returns any order by ID
def get_order(order_id):
return Order.find(order_id)
# Good - checks ownership
def get_order(order_id, current_user):
order = Order.find(order_id)
if order.user_id != current_user.id:
raise AuthorizationError("Not your order")
return order
Function Level Authorization (vs. BFLA):
# Bad - anyone can call
@app.route('/api/admin/users', methods=['DELETE'])
def delete_user(user_id):
User.delete(user_id)
# Good - checks role
@app.route('/api/admin/users', methods=['DELETE'])
@require_role('admin')
def delete_user(user_id):
User.delete(user_id)
Property Level Authorization:
# Return different fields based on role
def serialize_user(user, requester):
data = {'id': user.id, 'name': user.name}
if requester.is_admin:
data['email'] = user.email
data['last_login'] = user.last_login
return data
Use policy engines. OPA (Open Policy Agent), Casbin - externalize authorization logic. Centralized, testable, auditable.
How to implement rate limiting and throttling?
Rate limiting strategies:
- Per user/API key (authenticated requests)
- Per IP (unauthenticated / as fallback)
- Per endpoint (sensitive endpoints stricter)
- Sliding window vs. fixed window
Example tiers:
- Anonymous: 100 requests/hour
- Basic user: 1000 requests/hour
- Premium: 10000 requests/hour
- Internal service: higher limits with monitoring
Implementation options:
- API Gateway (Kong, Apigee, AWS API Gateway)
- Reverse proxy (nginx, HAProxy)
- Application-level (redis-based counters)
- Cloud-native (AWS WAF, Cloudflare)
Response handling:
- Return 429 Too Many Requests
- Include
Retry-Afterheader - Explain limit in response body
- Consider exponential backoff in clients
Beyond request rate:
- Payload size limits
- Query complexity limits (GraphQL)
- Concurrent connections limit
- Cost-based limiting (expensive operations)
How to validate input and protect against injection?
Validate everything:
- Schema validation (JSON Schema, OpenAPI validation)
- Type checking (string, integer, email, UUID)
- Length limits
- Allowed values (enums)
- Format validation (regex with care)
Sanitize/escape output, not input. Principle: validate input strictly, encode output for context (HTML, SQL, shell).
SQL Injection via API:
# Bad - string concatenation
query = f"SELECT * FROM users WHERE name = '{name}'"
# Good - parameterized queries
query = "SELECT * FROM users WHERE name = %s"
cursor.execute(query, (name,))
NoSQL Injection (MongoDB):
# Bad - accepts object from user
db.users.find(request.json) # User sends {"$gt": ""}
# Good - validate expected structure
name = request.json.get('name')
if not isinstance(name, str):
raise ValidationError()
db.users.find({'name': name})
Command Injection:
# Bad - user input in shell
os.system(f"ping {user_input}")
# Good - use libraries, not shell
import subprocess
subprocess.run(['ping', '-c', '1', validated_hostname], check=True)
How to protect API against SSRF?
SSRF scenario: API accepts URL parameter, fetches resource:
# Vulnerable
@app.route('/api/fetch')
def fetch_url():
url = request.args.get('url')
return requests.get(url).content # Attacker: url=http://169.254.169.254/
Mitigations:
- Whitelist allowed domains/IPs
- Block private IP ranges (10.x, 192.168.x, 169.254.x, 127.x)
- Block cloud metadata endpoints (169.254.169.254)
- Use DNS resolution and check resolved IP before connecting
- Disable redirects or validate redirect targets
- Use egress proxy with restrictions
# Better
ALLOWED_HOSTS = ['api.trusted.com', 'cdn.trusted.com']
def fetch_url(url):
parsed = urlparse(url)
if parsed.hostname not in ALLOWED_HOSTS:
raise SecurityError("Host not allowed")
# Additional: resolve DNS, check IP
return requests.get(url, allow_redirects=False).content
How to monitor and detect attacks on API?
Logging essentials:
- All authentication attempts (success/failure)
- Authorization failures
- Rate limit hits
- Error responses (4xx, 5xx patterns)
- Unusual patterns (off-hours, unusual geolocations)
Do NOT log:
- Full credentials/tokens
- PII unnecessarily
- Sensitive business data
Anomaly detection:
- Baseline normal traffic patterns
- Alert on deviations (volume, endpoints, user agents)
- Sequence analysis (unusual API call sequences)
API-specific monitoring:
- Authentication failure spikes (credential stuffing)
- Sequential ID access (BOLA exploitation)
- Unusual data volume per user (data exfiltration)
- Deprecated endpoint access
Tools:
- API Gateways with analytics (Kong, Apigee)
- SIEM integration (Splunk, ELK, Datadog)
- Specialized API security (Salt Security, Traceable, Noname Security)
How to test API security?
DAST (Dynamic Application Security Testing):
- OWASP ZAP (free, scriptable)
- Burp Suite (professional standard)
- Postman security tests
- API-specific scanners (Astra, APIsec)
SAST for API code:
- SonarQube rules for API security
- Semgrep custom rules
- CodeQL queries
Manual testing checklist:
- Authorization testing (access other users’ resources)
- Authentication bypass attempts
- Injection testing (SQL, NoSQL, command)
- Rate limiting validation
- Error message information disclosure
- Deprecated endpoint discovery
- IDOR (Insecure Direct Object Reference) testing
Fuzzing:
- Invalid input types
- Boundary values
- Malformed JSON/XML
- Unicode edge cases
Penetration testing:
- Regular professional pentests
- Bug bounty programs for APIs
- Red team exercises
How to build secure API development lifecycle?
Design phase:
- Threat modeling for API
- Define authentication/authorization requirements
- Plan rate limiting strategy
- Design for minimal data exposure
Development:
- Secure coding guidelines for API
- Code review with security focus
- Pre-commit hooks for secrets detection
- Dependency scanning
Testing:
- Security unit tests (authorization logic)
- Integration security tests
- DAST in CI/CD pipeline
- Manual security review for sensitive endpoints
Deployment:
- Security configuration review
- Secrets management (not in code)
- HTTPS only, proper TLS config
- API Gateway security features enabled
Operations:
- Continuous monitoring
- Incident response plan for API breaches
- Regular security assessments
- Deprecation process for old versions
Table: API Security Checklist
| Category | Control | Priority | How to check | Tools |
|---|---|---|---|---|
| Authentication | OAuth 2.0 / OIDC implementation | Critical | Code review, pentest | Auth0, Keycloak |
| Authentication | JWT proper validation | Critical | Unit tests, DAST | jwt.io, Burp |
| Authentication | Token expiration < 15 min | High | Config review | - |
| Authorization | Object-level access checks | Critical | Code review, pentest | OPA, Casbin |
| Authorization | Function-level access checks | Critical | Code review, pentest | Role-based tests |
| Authorization | Property-level filtering | High | Code review | Custom tests |
| Input Validation | Schema validation | High | Unit tests, fuzzing | JSON Schema, AJV |
| Input Validation | SQL injection prevention | Critical | DAST, code review | SQLMap, Burp |
| Rate Limiting | Per-user/IP limits | High | Load testing | API Gateway, Redis |
| Rate Limiting | Payload size limits | Medium | Config review | nginx, API Gateway |
| Encryption | HTTPS only | Critical | SSL Labs test | SSL Labs, testssl.sh |
| Encryption | TLS 1.2+ only | High | Config scan | nmap, SSL Labs |
| Logging | Auth events logged | High | Log review | SIEM, ELK |
| Logging | No secrets in logs | Critical | Log audit | grep, log analysis |
| Monitoring | Anomaly detection | Medium | Alert review | Datadog, specialized tools |
| Inventory | All endpoints documented | High | API discovery | Swagger, API catalog |
| Inventory | Old versions deprecated | Medium | Traffic analysis | API Gateway analytics |
API security requires a systematic approach - from design through development to operations. One unsecured endpoint can compromise the entire application. OWASP API Top 10 is a good starting point, but not everything - each API has a unique attack surface.
Key takeaways:
- BOLA (Broken Object Level Authorization) is the most common vulnerability - always check ownership
- Authentication is not authorization - having a token ≠ having the right to a resource
- Rate limiting protects against abuse and DoS - implement at multiple levels
- Input validation must be strict - trust nothing from outside
- Monitoring is key - you don’t know you’re being attacked if you’re not looking
- API inventory - you must know what you have to protect it
- Test regularly - automated + manual + pentest
API security is a continuous process, not a one-time project. Every new endpoint is a new attack surface. Every change requires security review.
ARDURA Consulting provides security and DevSecOps specialists through body leasing with experience securing APIs for enterprise applications. Our experts help design, implement, and test secure APIs. Let’s talk about securing your interfaces.