Security Blog

API Security Testing: How to Find Vulnerabilities in Your REST API

REST APIs have a unique attack surface: auth bypass, IDOR, injection via JSON, excessive data exposure, and rate limiting gaps. Here's how to test yours systematically.

api securityrest apiappsecowasp api

The OWASP API Security Top 10 exists as a separate list from the main OWASP Top 10 because APIs have a distinct attack surface. There's no UI to guide exploration — everything is exposed programmatically, authenticated state is complex, and the data exchanged is often more sensitive than what a browser receives.

The sections below cover the five most commonly exploited items from that list. Here's how to approach each one systematically.

API1: Broken Object Level Authorization (BOLA)

The most common API vulnerability. An endpoint accepts an object ID and returns the object without checking whether the requesting user owns it.

GET /api/v1/orders/8472
Authorization: Bearer user_a_token

# Returns user_b's order if the API doesn't check ownership

How to test: Authenticate as User A. Collect IDs from normal API use. Authenticate as User B. Attempt to access User A's IDs. A 200 response is a confirmed BOLA vulnerability.

How to fix: Every query that retrieves a resource by ID must filter by the authenticated user: WHERE id = $1 AND user_id = $2.

API2: Broken Authentication

Authentication flaws specific to APIs: tokens that don't expire, JWTs that aren't validated, authentication endpoints with no rate limiting, or API keys in URLs (logged by proxies and servers).

# JWT with algorithm:none accepted — attacker removes signature and sets alg:none
# Test: decode your JWT, modify the payload, use alg:none, send it
eyJhbGciOiJub25lIn0.eyJ1c2VySWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.

How to test: Check if expired tokens are accepted. Try alg:none JWT bypass. Test login endpoint rate limiting (automate 100 attempts). Look for API keys in query params in your logs.

API3: Broken Object Property Level Authorization

The API returns more fields than the user should see, or accepts more fields in writes than intended (mass assignment).

# Excessive data exposure: returns password hash and internal IDs
GET /api/v1/users/me
{
  "id": 123,
  "email": "[email protected]",
  "passwordHash": "$2b$10$...",
  "stripeCustomerId": "cus_abc"
}

# Mass assignment: API accepts fields it shouldn't
PATCH /api/v1/users/me
{"email": "[email protected]", "role": "admin"}  # role accepted?

How to test: Inspect all API responses for fields that shouldn't be client-visible. Try adding unexpected fields in write requests (role, isAdmin, subscription). Use a field enumeration tool to discover undocumented properties.

API4: Unrestricted Resource Consumption

Missing rate limits on expensive endpoints. No pagination limits. Endpoints that allow arbitrary-size array inputs. Webhooks that can be triggered at unlimited frequency.

# Test: send a large batch request
POST /api/v1/users/bulk-lookup
{"ids": [1,2,3,...,10000]}  # does the server process all 10,000?

# Test: rapid-fire the search endpoint
for i in {1..1000}; do curl /api/search?q=test; done

How to fix: Rate limiting at the reverse proxy or API gateway layer. Explicit max page sizes and max batch sizes. Request size limits.

API5: Server-Side Request Forgery (SSRF)

An API endpoint that fetches a user-supplied URL. In cloud environments, this is critical — an attacker provides the AWS metadata endpoint URL and gets temporary credentials.

# Test: provide cloud metadata URLs as inputs to any URL-accepting parameter
POST /api/v1/webhooks
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}

POST /api/v1/import
{"imageUrl": "http://[::ffff:169.254.169.254]/latest/meta-data/"}  # IPv6 bypass

How to fix: Allowlist valid URL schemes and domains for any endpoint that fetches external URLs. Block private IP ranges and cloud metadata endpoints in egress filtering.

Systematic API testing approach

Step 1: API discovery

You can't test what you don't know about. Map all endpoints by examining:

  • OpenAPI/Swagger specs (if available)
  • Network traffic from the frontend (browser DevTools Network tab)
  • JavaScript source for fetch calls and API client constructors
  • Crawler discovery against running endpoints

Step 2: Authentication coverage

For every endpoint, test it with: no auth token, an expired token, a valid token for a different user, a valid token for a lower-privilege role. Any unexpected 200 response is a finding.

Step 3: Input fuzzing

Send unexpected values to every input field: SQL payloads, XSS payloads, path traversal sequences, very large values, negative numbers, null, arrays where scalars are expected. Look for error messages that reveal stack traces or database structure.

Step 4: Business logic testing

This requires understanding your application. Can you apply a coupon twice? Order negative quantities? Access a resource in a state where it shouldn't be accessible (e.g., a soft-deleted item)? This is the manual pentester's territory.

How BattleTest tests APIs

BattleTest's live battletest crawler identifies API endpoints and their parameter shapes, then runs targeted security tests: BOLA testing with two-session cross-access, injection payload fuzzing against JSON body fields, header analysis for auth weaknesses, and SSRF payload injection into URL-type parameters. Findings include confirmed reproduction steps — not just "potential vulnerability."

Try BattleTest

Catch this class of bug before it ships.

BattleTest reviews every PR for injection flaws, leaked secrets, and CVEs — then battle-tests your live infrastructure the way an attacker would.

Run an API security assessment against your endpoints →

Free for public repos · Private repos from $20/mo · No credit card required