technique
stage: discover
2 min read
Web and API security testing
Most serious web findings come from a short list of questions: who can see what, who can change what, and what happens to input that is not what the developer expected. A proxy and two accounts answer most of them.
Burp SuiteOWASP ZAPffuf (authorized content discovery)PostmancurlNuclei (authorized targets)
Set up
- Route your browser through an intercepting proxy (Burp, ZAP) so you can see, replay and modify every request.
- Create at least two test accounts at the same privilege level, and one at a higher level if scope allows. Authorization bugs are found by comparing accounts.
- Map the application: pages, API routes, parameters, roles, file uploads, integrations. The API schema (OpenAPI) is a gift when it exists.
- Note which requests are authenticated and how: cookie, bearer token, API key.
A testing checklist
Work through the categories of the and the Web Security Testing Guide. The domain on this site for the OWASP Top 10 shows the fix for each; here is how to look for it.
- Access control: replay account A's requests with account B's token; change ids; call admin routes as a normal user; try methods the UI never uses.
- Authentication and session: on login and reset, session expiry and rotation, cookie flags, token validation.
- Injection: send unexpected characters and types to every parameter, headers and JSON fields, and watch for errors or changed behavior.
- Business logic: skip steps, repeat steps, change quantities and prices, race two requests at once.
- Misconfiguration: verbose errors, debug endpoints, directory listing, permissive , missing headers.
- File handling: type and size checks, path handling, where uploads are stored and served.
Example: an authorization check with two accounts
Automate the repetitive comparison, and keep the test read-only. This script, for an authorized target, checks whether account B can read objects created by account A.
import requests
BASE = "https://api.example.com/v2"
A = {"Authorization": "Bearer <token for tester-a>"}
B = {"Authorization": "Bearer <token for tester-b>"}
# objects that account A owns (listed with A's own token)
ids = [o["id"] for o in requests.get(f"{BASE}/invoices", headers=A, timeout=10).json()]
for oid in ids:
r = requests.get(f"{BASE}/invoices/{oid}", headers=B, timeout=10)
verdict = "VULNERABLE" if r.status_code == 200 else "ok"
print(f"{oid}: B -> {r.status_code} {verdict}")ffuf -u https://app.example.com/FUZZ -w common-paths.txt -rate 10 -mc 200,204,301,302,401,403 -o ffuf.jsonTest APIs deliberately
- Object-level authorization () and function-level authorization are the most common API findings.
- : send extra fields (role, isAdmin, price) that the client never sends.
- Excessive data exposure: the API returns whole objects and the UI hides fields; read the raw response.
- Rate limits and resource limits on expensive operations.
- Version drift: old API versions and undocumented routes that lack the controls of the new ones.
- Stay within the : test with test data, avoid destructive calls, and keep your request rate low.
connections on the map
- Reconnaissance and attack surfacefeedsWeb and API security testing
- Web and API security testingcan lead toAttack paths and privilege escalation
updated on 14/10/2026 · sources to go deeper · report an error
in other domains
- A01 Broken Access Controlowasphow to find what the other teaches you to fix
- A05 Injectionowasphow to test what the other teaches you to fix
Study before
Unlocks
test what you learned
Loading questions…