Strobesstrobes
Platform
Solutions
Resources
Customers
Company
Pricing
Book a Demo
Strobesstrobes

Strobes connects every exposure signal to autonomous action, so security teams fix what matters, prove what works, and stop chasing noise.

Book a DemoTalk to an expert
ISO 27001SOC 2CREST
  • Platform
  • Platform Overview
  • Agentic Exposure Management
  • AI Agents
  • Integrations
  • API & Developers
  • Workflows & Automation
  • Analytics & Reporting
  • Solutions
  • Exposure Assessment (EAP)
  • Attack Surface Management
  • Application Security Posture
  • Risk-Based Vulnerability Management
  • Adversarial Exposure Validation (AEV)
  • AI Pentesting
  • Pentesting as a Service
  • CTEM Framework
  • By Industry
  • Financial Institutions
  • Technology
  • Retail
  • Healthcare
  • Manufacturing
  • By Roles
  • CISOs
  • Security Directors
  • Cloud Security Leaders
  • App Sec Leaders
  • Resources
  • Quick Agentic Pentest
  • Blog
  • Customer Stories
  • eBooks
  • Datasheets
  • Videos & Demos
  • Exposure Management Academy
  • CTEM Maturity Assessment
  • Pentest Health Check
  • Security Tool ROI Calculator
  • Company
  • About Strobes
  • Meet the Team
  • Trust & Security
  • Contact Us
  • Careers
  • Become a Partner
  • Technology Partner
  • Partner Deal Registration
  • Press Release

Weekly insight for security leaders

CTEM research, agentic AI trends, and what's actually moving the needle.

© 2026 Strobes Security Inc. All rights reserved.

Privacy PolicyTerms of ServiceCookie PolicyAccessibilitySitemap
Back to Blog
What Is API Penetration Testing?
Application SecurityPenetration Testing

What Is API Penetration Testing?

Shubham JhaOctober 27, 20247 min read

Table of Contents

  • What is API penetration testing?
  • The attack surface is the contract, not the UI
  • How do you prove a BOLA in one request?
  • How do you forge and crack JWTs?
  • What does an API pentest actually deliver?
  • Scanners miss authorization, and the fix is configuration
  • Frequently asked questions
  • Sources and references

Authors

S
Shubham Jha

Share

Table of Contents

  • What is API penetration testing?
  • The attack surface is the contract, not the UI
  • How do you prove a BOLA in one request?
  • How do you forge and crack JWTs?
  • What does an API pentest actually deliver?
  • Scanners miss authorization, and the fix is configuration
  • Frequently asked questions
  • Sources and references

Authors

S
Shubham Jha

Share

TL;DR
  • ✓API penetration testing attacks REST, GraphQL, and gRPC endpoints directly at the HTTP layer, where there is no UI to limit what you send.
  • ✓The bugs that matter are authorization failures: BOLA (API1) and BFLA (API5) drive most real API breaches, and scanners cannot find them.
  • ✓Proof is a paired request and response: a 200 returned to the wrong account is the deliverable, not a scanner alert.
  • ✓You need at least two accounts. One token's reach into another account's objects is the test no automated tool will run for you.
  • ✓Fixes are specific and config-level: object-level authZ inside each resolver, a JWT alg allowlist, writable-property allowlists, and per-identity rate limits.

Salt Security's research has tracked malicious API traffic climbing into the hundreds of percent year over year, and Gartner called it years ago: APIs are now the most frequent attack vector for web applications. The reason is unglamorous. An API hands an attacker the raw data contract, and a single missing ownership check can leak an entire table one integer at a time. That is the bug class API penetration testing exists to catch, and it is exactly the class your DAST scanner reports as clean.

This guide is the working version, not the brochure version. You will see the actual request that proves a Broken Object Level Authorization bug, a forged alg:none token, a cracked JWT secret, a findings table from a real report, and the configuration changes that close each gap. If you run any kind of API, this is the assessment that finds what the front end was hiding.

Table of contents
  1. What is API penetration testing?
  2. The attack surface is the contract, not the UI
  3. How do you prove a BOLA in one request?
  4. How do you forge and crack JWTs?
  5. What does an API pentest actually deliver?
  6. Scanners miss authorization, and the fix is configuration

What is API penetration testing?

API penetration testing is the manual and AI-assisted exercise of attacking an application's API endpoints directly, looking for flaws in authorization, authentication, input handling, and business logic that a user interface would normally hide. You work against the raw request and response: forging object IDs, replaying one account's token against another's data, sending fields the client never renders, and hammering endpoints that forgot to rate-limit.

The work is structured around the OWASP API Security Top 10, which names the risk classes worth your time. The top of that list is not injection. It is authorization, because an API has no server-rendered template deciding what you get to see.

That is the core insight the rest of this guide builds on. A scanner can tell you a header is missing. It cannot tell you that GET /api/v1/orders/1043 just returned a different tenant's order, because it has no concept of who owns object 1043. A tester with two accounts can prove it in one request, and that proof is what you are paying for.

The attack surface is the contract, not the UI

This is the single biggest difference from web application testing, and it reframes everything. A web app pentest often starts by crawling rendered pages to discover functionality. An API pentest starts from the contract itself: an OpenAPI or Swagger file, a Postman collection, a GraphQL introspection dump, or captured mobile traffic. Every parameter the backend will accept is in scope, documented or not.

Three consequences follow directly:

  • Authorization dominates. With no template gating what you see, object-level and function-level checks are the whole game. See the business-logic angle for how this extends into workflows.
  • APIs leak by default. A REST endpoint that serializes a full database row will happily ship a password hash or an internal is_staff flag to any client, trusting the front end to hide it. When you talk to the API directly, the front end is not your problem.
  • Old versions linger. /api/v1/ often survives a rewrite to /api/v2/, with weaker or absent auth on the deprecated path. That is OWASP API9, Improper Inventory Management, and it is a reliable foothold.
Why APIs are the front line
API1
BOLA ranked the #1 OWASP API risk (2023)
2 of 5
of the OWASP API Top 5 are authorization failures
Most
Salt Labs: API attack traffic up sharply YoY
0
of these found by a typical DAST scanner

How do you prove a BOLA in one request?

You authenticate as user A, capture a request that fetches an object by ID, then replay it pointed at an object you do not own. The status code tells you everything. Here is the exchange that proves it, lightly annotated:

GET /api/v1/accounts/2001/statements HTTP/1.1
Host: bank.example.com
Authorization: Bearer <user-A-token>        # token belongs to user A

--- response ---
HTTP/1.1 200 OK                              # <- expected 403, got 200
{ "account": 2001,
  "owner": "userB@example.com",              # <- this is NOT user A
  "balance": 84210.55 }

User A's token returned user B's bank statement. That 200 is the proof. Because the ID is a sequential integer, the bug is exploitable at scale by scripting the increment, which is why it scores critical rather than medium.

The dangerous sibling is mass assignment, where the framework binds every JSON key in the body straight onto the model. A profile update accepts fields the client never shows:

PATCH /api/v1/users/me HTTP/1.1
Authorization: Bearer <low-priv-token>
Content-Type: application/json

{ "displayName": "akhil",
  "role": "admin",                           # <- field the UI never sends
  "emailVerified": true }

--- response ---
HTTP/1.1 200 OK
{ "id": 88, "displayName": "akhil",
  "role": "admin" }                          # <- server bound it: you are now admin

The server echoed "role": "admin" back, which means it accepted the smuggled field and you just escalated yourself. Two requests, two critical findings, zero scanner involvement.

One caveat keeps testers honest here: a 200 alone is not always a BOLA. If the object you requested happens to be public, or the API returns a sanitized stub for objects you do not own, you have a false positive. The discipline is to confirm with a second account: fetch object 2001 as user A and as user B, and compare. If both see the full record, the ownership check is missing; if only the owner sees the sensitive fields, it is enforced. That paired comparison is the difference between a finding and a guess, and it is the exact step a scanner cannot take.

How do you forge and crack JWTs?

You attack the token itself, because a bearer token the server trusts is the cheapest route to every other user. JWTs fail in a few repeatable ways. The first is honoring alg:none: you rewrite the header, strip the signature, and tamper a claim. A library that respects none accepts a forged, unsigned token:

# Original header:  {"alg":"HS256","typ":"JWT"}
# Forged header:    {"alg":"none","typ":"JWT"}
# Forged payload:   {"sub":"88","role":"admin"}   # <- escalated claim

$ python3 jwt_tool.py <token> -X a    # -X a = alg:none exploit
[+] Signature removed, alg set to none
[+] Forged token:
    eyJhbGciOiJub25lIn0.eyJzdWIiOiI4OCIsInJvbGUiOiJhZG1pbiJ9.
                                                  # <- empty signature, accepted by server = critical

The second is a weak HMAC secret. If the token is HS256-signed with a guessable key, you crack it offline and then sign anything you like:

$ hashcat -a 0 -m 16500 token.jwt rockyou.txt    # -m 16500 = JWT mode

eyJhbGciOiJIUzI1NiJ9...<snip>:s3cr3t-key-2019    # <- secret recovered
Session..........: hashcat
Status...........: Cracked

With the secret in hand you sign a token carrying "role":"admin" and walk in. The other repeatable checks are kid header injection (point it at ../../dev/null or an SQL fragment for key confusion) and a flipped signature byte that still returns 200, which means the server never verified it at all.

How an API pentest runs
1
Discovery
Import the spec, proxy the mobile app, brute-force routes with Kiterunner. Build the full inventory.
2
Auth
Two-plus accounts. Replay each request as the other principal to test BOLA and BFLA.
3
Input
Injection, mass assignment, SSRF, excessive data exposure on every parameter.
4
Logic
Sequencing, replay, and race conditions on stateful flows like checkout and transfers.
5
Report
Categorize against OWASP API, score CVSS, prove with a request/response pair.

What does an API pentest actually deliver?

It delivers categorized findings, each proven with a paired request and response and scored with CVSS, plus a remediation that names the exact control. The table below is the shape of a real report excerpt: this is what experience looks like on paper, not a list of scanner hits.

On a recent assessment of a fintech lender, the documented API looked locked down, but a capture from the mobile app revealed an undocumented /internal/v1/ namespace with no authorization at all. We pulled loan records for arbitrary borrowers by ID, then chained that into the mass-assignment write above to flip our own account to a privileged role. The documented endpoints were never the bug. Testing only what the client hands you is the most common mistake teams make, and it is exactly how an API earns a clean scanner report while being wide open.

For the full sequence end to end, work through the API penetration testing checklist and the tools we reach for at each phase.

Findings table (report excerpt)
FindingSeverity (CVSS)EvidenceFix
BOLA on /accounts/{id}/statementsCritical (9.1)User A token returned user B balance, HTTP 200Object-level ownership check in controller
Mass assignment of role on PATCH /users/meHigh (8.1)Injected role:admin echoed in 200 responseAllow-list writable properties; reject role
JWT accepts alg:noneCritical (9.8)Unsigned forged token authenticated as adminPin alg allowlist [RS256]; reject none
Undocumented /internal/v1/ namespaceHigh (8.2)Unauthenticated loan records via mobile captureDecommission or auth + inventory the route
No rate limit on /auth/otpMedium (6.5)10,000 OTP guesses, zero 429 responsesPer-identity throttle + lockout on OTP

Scanners miss authorization, and the fix is configuration

Scanners miss the worst API bugs because every one of them depends on knowing who should have access, and a DAST tool has no model of tenancy, ownership, or business state. It fires payloads and grades responses; it will not invent a second account to compare against, so it cannot see that a 200 returned someone else's record. BOLA, BFLA, and broken business logic all require a tester who knows what a correct authorization decision looks like. The same blind spot explains the false negatives that matter most: a scanner reports a clean run not because the API is safe, but because every malicious request it sent came back 200 and it had no second identity to prove the response was wrong.

The fixes are specific and live in configuration, not in a security-awareness slide:

  • BOLA: enforce an object-level ownership check inside the resolver or controller for every resource, not at the gateway. The gateway authenticated the caller; it did not authorize the object.
  • Broken auth: validate the JWT alg against a fixed allowlist (for example ["RS256"]) and reject none outright. Never let the token choose its own algorithm.
  • Mass assignment: allow-list the properties a request may write instead of binding the whole body. role, tenantId, and verified should never be client-settable.
  • Resource consumption: rate-limit per identity, not per IP, so a rotating X-Forwarded-For cannot bypass it.

Testing the contract directly with multiple authenticated roles is the only reliable way to catch these before they become a disclosure event. Running it on every deploy instead of once a year is where agentic pentesting changes the economics.

Frequently asked questions

What is the difference between API testing and API penetration testing?
API testing usually means functional or performance testing: does the endpoint return the right data quickly. API penetration testing is adversarial. It tries to break authorization, authentication, and business logic to reach data or functions you should not be able to touch, and it proves each gap with a request and response pair.
How much does an API penetration test cost?
A focused REST API of 20 to 40 endpoints typically runs from roughly 7,000 to 15,000 USD as a point-in-time engagement, depending on region and firm. Cost scales with endpoint count, number of roles, GraphQL complexity, and the depth of stateful workflows. Continuous, agentic approaches change this from a one-off invoice to an ongoing subscription.
How long does an API penetration test take?
A REST API with 20 to 40 endpoints usually takes 3 to 5 days of active testing. Large surfaces with many roles, GraphQL introspection, and complex business logic can run two weeks or more. Scope is driven by endpoint count, the number of privilege levels, and how stateful the workflows are.
Is REST or GraphQL harder to pentest?
They are different, not strictly harder. REST spreads the surface across many routes, so discovery and versioning matter most. GraphQL hides everything behind one endpoint and returns 200 even for errors, so the work is almost entirely manual and shifts toward schema recovery, nested-resolver authorization, and query-cost abuse. See our GraphQL security testing guide for the specifics.
Can API penetration testing be automated?
Parts of it. Schemathesis, ffuf, and Burp automate discovery, fuzzing, and spec-driven testing. But authorization and business-logic flaws require reasoning about who owns what, so the highest-value findings still need a human or an agentic system. Tools generate candidates; judgment confirms the bug.
Is API penetration testing required for compliance?
It is increasingly expected under PCI DSS, SOC 2, and similar frameworks that require testing of in-scope applications. APIs that handle cardholder or regulated data fall within those testing requirements even when they have no user interface at all.

Sources and references

  • OWASP API Security Top 10 (2023)
  • Salt Security State of API Security Report
  • Gartner: API Security best practices
S
Shubham Jha
Security Researcher, Strobes
Shubham Jha leads offensive security research at Strobes, focused on web and API exploitation and red team tradecraft.
Tags
API SecurityPenetration TestingApplication Security

Stop chasing vulnerabilities Start reducing exposure

See how Strobes AI agents validate and fix your most critical exposures automatically.

Book a Demo
Continue Reading

Related Posts

Vulnerability validation: why most of your scanner backlog is noise - Strobes
Exposure ValidationApplication Security

Vulnerability Validation: Why Most of Your Scanner Backlog Is Noise

Vulnerability validation proves which scanner findings are real, reachable, and exploitable. Why manual triage fails and how agentic validation scales.

Jun 9, 202619 min
How to pentest single-page applications - React, Angular and Vue SPA security testing guide
Penetration TestingApplication Security

How to Pentest Single-Page Applications (React, Angular, Vue)

Learn how to pentest React, Angular, and Vue SPAs. Covers DOM XSS, client-side routing bypass, JS bundle secrets, and why traditional DAST scanners fail.

Jun 4, 202623 min
Bug bounty vs pentesting vs AI pentesting comparison featured image
Penetration TestingApplication Security

Bug Bounty vs. Pentesting vs. AI Pentesting: Which Model Fits Your AppSec Program?

Bug bounty vs pentesting vs AI pentesting: compare costs, coverage, compliance, and when to use each model. Build a layered AppSec testing strategy.

Jun 4, 202621 min