APIs, Attack Patterns, and Why Your WAF Isn't Enough
I spent a stretch of time studying for a potential role at Salt Security a while ago. Salt is one of the companies that helped define dedicated API security as its own category, which sounds like vendor marketing until you actually look at what the API threat landscape has become. This post is what I took away from that prep. I work in enterprise security at Fortinet, so some of this will have comparisons drawn from there, but the API security fundamentals apply everywhere. The goal is one honest, thorough piece on what APIs are, how attacks against them actually work, and why the tools most companies are using can't catch most of it. These are my personal study notes, not an official position from Fortinet or any vendor discussed here.
There's a separate post on LLMs, MCP servers, and how the agentic AI stack fits into this picture. That one can stand on its own. This one is the foundation.
What an API Actually Is
An API is a contract between two systems. One side defines the rules: here's what I accept, here's the format, here's what you'll get back. The other side follows those rules to get something done. That's the whole thing.
The restaurant analogy is overused but accurate. The menu is the API specification. Your order is the request. The kitchen processes it. You get food back. You never walk into the kitchen, you don't know whether the stove is gas or electric, and you don't need to. The interface abstracts all of that away.
Replace "food" with your bank balance, your Spotify queue, an AI model's output, or a shipping status update and you have modern software. Everything connects through APIs. The mobile banking app, the payment gateway, the inventory system, the AI assistant reading your emails. When you log into your banking app and a number appears, that number came back from an API call. When a request fails, something in that chain broke.
Types of APIs Worth Knowing
Not all APIs carry the same risk profile.
External APIs are exposed to the internet. They naturally attract the most scanning, probing, and attack traffic because anyone can reach them.
Internal APIs sit inside the network perimeter, meant for communication between systems within an organization. The assumption built into most internal APIs is that traffic from inside the network is trustworthy. Attackers who gain internal access find that assumption very useful.
Partner APIs expose limited functionality to specific external parties, like suppliers or integration partners. The access is controlled but it's still crossing an organizational boundary.
Third-party APIs are services your own application calls. Stripe for payments, Twilio for SMS, an AI model API. If any of those third-party services are compromised, your application may consume bad data or malicious responses unless it validates what comes back.
Shadow APIs are the genuinely alarming category. These are APIs running in production that nobody officially knows about. A developer builds a test endpoint, ships the feature, forgets to take the test endpoint down. It's in production, potentially unauthenticated, outside any security review process, absent from every piece of documentation. API discovery projects often find far more APIs than the organization thought it had. That is the real problem: the inventory is usually wrong before the security program even starts.
Zombie APIs are old versions still running. The company is on v3. V1 and v2 are still running because some legacy client uses them, and they lack all the security controls added in the new versions. Attackers hunt these specifically.
HTTP: How APIs Actually Communicate
Almost every API you'll encounter uses HTTP or its encrypted version, HTTPS. Understanding HTTP is understanding the mechanics of API communication.
Methods
Every HTTP request has a method telling the server what kind of operation is being requested.
GET retrieves data. No request body, just a URL. Read-only by design.
POST creates a resource. The data being submitted lives in the request body.
PUT replaces a resource entirely. PATCH updates specific fields. Both carry data in the request body.
DELETE removes a resource. Should be restricted to authorized users, which not every API actually enforces.
Status Codes
Every response comes back with a three-digit status code. The first digit tells you the category.
2xx codes indicate success. 200 is the standard success response. 201 means something was created. 204 means success with nothing to return, common for DELETE operations.
3xx codes are redirects. The resource has moved, temporarily or permanently. These are mostly infrastructure plumbing.
4xx codes mean the request is the problem. 400 is a malformed request, bad JSON, a missing required field. 401 means the caller isn't authenticated. 403 means the caller is authenticated but doesn't have permission. 404 means the resource doesn't exist. 429 means the caller has been rate limited.
5xx codes mean the server is the problem. 500 is an internal server error, something crashed. 502 is a bad response from an upstream service, common in microservices environments. 503 means the server is overloaded or down.
The practical triage rule: 4xx means look at the request. 5xx means look at the server. A 401 and a 403 sound similar but point in completely different directions. 401 is "who are you?" and means check authentication. 403 is "I know who you are, but no" and means check authorization logic. Getting that distinction wrong wastes time.
Troubleshooting an API Issue
The process is the same whether you're debugging your own integration or helping a customer understand why something broke.
Start by getting a clear picture of what should have happened versus what did. This sounds obvious and it matters more than people think. A surprising number of reported API issues disappear when you actually look at what request was sent.
Confirm the specific endpoint, the HTTP method, the parameters, and the authentication headers or tokens. A wrong endpoint, an expired token, or a missing required field accounts for a lot of reported failures.
Reproduce it. Build the exact request in Postman or cURL and fire it yourself. If you can replicate the issue, you've already narrowed the problem significantly.
Look at the response. The status code is the first signal. The response body often contains an error message that tells you exactly what broke.
If you're dealing with something that only happens in a real browser session and won't reproduce cleanly in Postman, get a HAR file. A HAR is an HTTP Archive file that captures every request and response the browser made during a session, including headers, timing, and payloads. It's a complete playback of the network conversation and it often surfaces things that don't show up in isolated reproduction attempts.
When the issue is server-side, meaning you're getting 5xx responses, go to the server logs. Modern observability tools like Datadog, New Relic, or Splunk let you search by request ID, trace ID, timestamp, or endpoint. You're looking for the log entry corresponding to the failed request.
In those logs, you're usually looking for a stack trace. A stack trace is the sequence of function calls the server made before something broke, printed in the log. It shows which functions were called, in which files, at which line numbers. The last line usually tells you exactly what failed: a null pointer, a database constraint violation, a connection timeout. That's what goes to engineering.
Knowing when to escalate is part of the skill. If the error is in server code, a database failure, or infrastructure, that's engineering's problem. If the issue is a bad request, wrong parameters, or an expired token, that's something you can diagnose and resolve without involving anyone else. A 500 doesn't automatically mean escalate. Sometimes a 500 is caused by a client sending something the server didn't expect. Rule out the client side first.
OpenAPI Specs and Swagger Files
A Swagger file, now officially called an OpenAPI Specification (OAS), is a structured machine-readable description of an API. It documents every endpoint, what HTTP method each endpoint accepts, what parameters are required, what authentication is needed, and what the response looks like.
It's written in JSON or YAML. A small fragment to give you a feel for the format:
paths:
/users/{id}:
get:
summary: Get a user by ID
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
id:
type: integer
name:
type: string
email:
type: string
That block is saying: there's an endpoint at /users/{id}. Send it a GET with a user ID in the path. You'll get a 200 back with a JSON object containing id, name, and email fields. It's a contract. If the API behaves correctly, the actual response matches the spec.
The public API documentation you see on sites like Stripe's developer portal is the human-readable version of the same information. Those docs are often generated from the Swagger file using tools like Swagger UI, which render the JSON or YAML into a polished webpage with search, example requests, and interactive "try it" buttons. The Swagger file is the blueprint. The docs are the finished presentation built on top of it.
A Swagger file usually describes one API surface or service boundary. A company with distinct services, like payments, notifications, and shipping, will often maintain separate specs for each.
The reason this matters from a security standpoint is API drift. When developers update their code without updating the spec, the documentation becomes inaccurate. Fields the spec doesn't mention start being accepted by the running code. Endpoints exist in production that appear in no documentation. Shadow parameters accumulate. Salt's platform ingests OpenAPI specs and compares them against live traffic to find exactly this gap. The spec is what correct is supposed to look like. Live traffic is what's actually happening. The difference between the two is the attack surface that nobody documented.
How Attackers Actually Work
Understanding the attack patterns makes the security tooling make sense. These aren't theoretical constructs.
Brute force attacks attempt to guess credentials by systematically trying combinations. High volumes of failed authentication attempts against an endpoint.
Credential stuffing takes username and password pairs from previous breaches, other sites where people have been compromised, and tries them against a target. It works because people reuse passwords. The goal is Account Takeover. The sophisticated version doesn't fire thousands of requests from one IP address. It uses botnets routing through residential proxies, each IP attempting a login once per hour. No single source ever triggers a rate limit. Meanwhile hundreds of thousands of accounts are being tested.
Scraping extracts data at scale by hitting API endpoints with automated scripts. Public APIs with no rate limits are prime targets. The result is bulk PII collection.
Low and slow attacks stay deliberately under detection thresholds. Two suspicious calls from one IP this week. Two from a different IP next week. Each request is a completely normal authenticated user accessing their own account, to all appearances. No rate limit is triggered. No individual event looks suspicious. Over time, the attacker has touched thousands of records. Simple rule-based detection usually has no good mechanism to correlate those two calls from last week with these two calls this week. Behavioral AI does.
Business logic abuse doesn't involve any technical vulnerability. The API works exactly as intended. The attack is automating legitimate transactions at machine speed. Scalping bots buying concert tickets. Fake review flooding. Bulk account creation for spam. A human fan might buy two tickets. A bot buys two thousand across five hundred accounts in ninety seconds. Every request is valid. Every response is a 200. The API did its job perfectly. The business outcome was a disaster.
OWASP API Top 10
OWASP maintains a community-developed list of the most critical API security risks. These are the shared language of enterprise API security conversations, and Salt's research maps heavily to this model.
API1: Broken Object Level Authorization (BOLA)
Also called IDOR. The most common API vulnerability class and the one API security people bring up constantly for a reason. An endpoint returns data identified by an ID, but doesn't check whether the requesting user owns that object. GET /accounts/456/statements works. Change 456 to 455 and you get someone else's statements. The server confirms authentication but skips ownership validation. Write a script to iterate through IDs at machine speed and you have a data breach using only valid requests and valid credentials. The Optus breach in Australia: an attacker found an API using sequential customer record IDs with no authentication required, wrote a loop, scraped the entire database.
API2: Broken Authentication
Tokens that never expire. JWTs signed with weak or hardcoded secrets, making them forgeable. Authentication endpoints vulnerable to credential stuffing. This is the primary vector for Account Takeover.
API3: Broken Object Property Level Authorization (BOPLA)
Two forms. Excessive data exposure: the API returns the full database row including salary, admin flags, and social security numbers, even though the application UI only displays the username. The attacker isn't looking at the UI. They're looking at the raw response. Mass assignment: the API accepts fields that should be read-only. POST /users/123 with {"admin": true} in the body and the server applies it. GitHub had a real mass assignment vulnerability where attackers could inject SSH keys into organizations via a specific API parameter.
API4: Unrestricted Resource Consumption
No rate limits, no size limits, no cost controls. Flooding an endpoint to cause a denial of service. For AI APIs specifically, a single complex query can be extremely resource-intensive. Bombarding an AI API with expensive queries runs up real compute bills fast.
API5: Broken Function Level Authorization (BFLA)
Regular authenticated users calling admin-level endpoints. The server checks whether the caller is logged in but not whether their role permits the specific action. DELETE /admin/users/{id} is discovered by a regular user through API documentation or by guessing URL patterns. They call it. The account is deleted. The server validated authentication but never validated authorization for that function. BOLA is accessing data you don't own. BFLA is executing actions you're not authorized to take. Different category of damage.
API6: Unrestricted Access to Sensitive Business Flows
No bug. The API works exactly as designed. The vulnerability is that nothing stops machine-speed automation of legitimate transactions. Scalping bots, fake review systems, automated price scraping. Each individual transaction is valid. What's missing is any defense against the volume and velocity.
API7: Server-Side Request Forgery (SSRF)
The API fetches a remote resource based on a URL the user supplies, without validating where that URL points. Supply http://169.254.169.254/latest/meta-data/ and the server fetches the AWS instance metadata endpoint from inside its own network, bypassing every external firewall. It returns cloud infrastructure credentials to the attacker. The Capital One breach is commonly discussed as an SSRF-style cloud metadata access chain: a request path was abused to reach AWS instance metadata and obtain credentials that had access to sensitive data. Over 100 million customer records were affected.
API8: Security Misconfiguration
One of the most commonly exploited API risk categories in Salt's reporting, and one of the easiest to underestimate because it often looks like basic deployment hygiene rather than an attack path. Verbose error messages that return stack traces including framework versions and internal directory paths. HTTP in production instead of HTTPS. Debug endpoints left active. Default credentials unchanged. Missing CORS restrictions. These are all functioning systems deployed insecurely.
API9: Improper Inventory Management
Shadow APIs and zombie APIs. You cannot secure what you don't know exists. Attackers find zombie APIs by downloading old mobile app files from third-party sites, decompiling them, and extracting the old API URLs. Those endpoints still point to the same backend database and lack the security controls added in newer versions.
API10: Unsafe Consumption of APIs
Your application trusts third-party API responses without validating them. If the payment provider is compromised and returns manipulated transaction amounts, your system processes fraudulent payments without question. Your attack surface is every API you call, not just the ones you own.
Why Traditional Security Tools Miss Most of This
The clearest summary of the problem: legacy tools catch bad code. Behavioral AI catches bad logic.
A WAF inspects each HTTP request against a dictionary of known attack signatures. SQL injection syntax, XSS payloads, known malicious patterns. It's good at what it does. The structural limitation is that it's stateless. It evaluates one request in complete isolation. No memory of previous requests, no session context, no awareness of what the same user was doing yesterday.
That architecture makes BOLA invisible. Every individual request is syntactically valid. A valid token, a valid endpoint, a valid response. Changing user_id=456 to user_id=455 matches no attack signature. The WAF passes it through every time.
A basic gateway enforces defined policies, but without behavioral context it usually cannot detect business logic abuse when every individual transaction is technically valid. It only knows about the APIs registered with it. Shadow APIs bypass it entirely.
Salt's approach is out-of-band passive traffic mirroring. Traffic goes to its destination normally, Salt analyzes a copy. That avoids adding an inline inspection point to the request path, which reduces latency and point-of-failure concerns compared with inline enforcement. The platform builds behavioral baselines for every user on every endpoint over time. When someone starts iterating through sequential object IDs at machine speed, that pattern is visible across the full history of their session, even if no single request ever appeared suspicious in isolation. Salt's research suggests that a large proportion of API attacks originate from authenticated users. The WAF and gateway have already waved those users through. Behavioral and context-aware API analysis is the layer best positioned to catch what happens next.
The three tools are complementary. WAF for signature detection. Gateway for access control and routing. Behavioral AI for the authenticated-user attack patterns that neither of the other two are architecturally built to see.
This doesn't mean WAFs are obsolete. They catch real attacks. The argument is that they catch a specific subset and that subset is getting smaller as attacks increasingly rely on valid credentials and legitimate API calls at unusual scale or unusual sequence. The gap between what WAFs see and what's actually happening is where most modern API attacks live.