-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Update REST Assessment Cheat Sheet: OpenAPI, JWT/OAuth2, BOLA, Mass Assignment, Rate Limiting #2100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -62,7 +62,129 @@ Analyzing collected requests to optimize [fuzzing](https://owasp.org/www-communi | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Lastly, when [fuzzing](https://owasp.org/www-community/Fuzzing), don't forget to emulate the authentication mechanism used. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## Assessing OpenAPI/Swagger-based REST APIs | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Modern REST APIs are commonly described using the [OpenAPI Specification (OAS)](https://www.openapis.org/), which replaces older formats such as WSDL and WADL. When an OpenAPI definition is available it significantly accelerates attack surface discovery. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **Locate the schema document.** Common default paths include: | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - `/openapi.json`, `/openapi.yaml` | ||||||||||||||||||||||||||||
| - `/swagger.json`, `/swagger.yaml` | ||||||||||||||||||||||||||||
| - `/api-docs`, `/v2/api-docs`, `/v3/api-docs` | ||||||||||||||||||||||||||||
| - `/docs`, `/redoc` | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Even when these paths are not advertised, try them — many frameworks expose them by default in production. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **Enumerate endpoints and parameters from the schema.** The schema lists every path, HTTP method, query parameter, request body field, and response shape. Use this to: | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - Build a complete list of endpoints that may not appear in the UI. | ||||||||||||||||||||||||||||
| - Identify parameters that the client never sends but the server still accepts. | ||||||||||||||||||||||||||||
| - Find endpoints marked `deprecated` that may receive less security scrutiny. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **Test undocumented fields.** Schemas can lag behind implementation. Submit additional JSON fields beyond those defined in the schema and observe whether they are accepted or reflected in responses — this is the basis for [Mass Assignment](#mass-assignment-in-json-apis) testing. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **Schema-driven fuzzing.** Tools such as [OWASP ZAP](https://www.zaproxy.org/) and [Schemathesis](https://schemathesis.readthedocs.io/) can import an OpenAPI definition and automatically generate test cases for each endpoint, including boundary values, type mismatches, and required-field omissions. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## JWT and OAuth2 Assessment | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Many modern REST APIs use [JSON Web Tokens (JWTs)](https://jwt.io/) for stateless authentication and [OAuth 2.0](https://oauth.net/2/) for delegated authorization. Misconfigurations in either are a frequent source of critical vulnerabilities. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ### JWT Assessment | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **Verify signature validation.** Swap the algorithm header to `alg: none` and remove the signature. A vulnerable server will accept the token without validating it. | ||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The actual attack retains the trailing . — the token structure must remain header.payload. (with an empty signature segment), not ▎ Strip the signature body but keep the trailing period: header.payload. |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **Test algorithm confusion.** If the server uses RS256 (asymmetric), try signing the token with HS256 using the server's *public key* as the HMAC secret. Servers that do not pin the expected algorithm may accept the forged token. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **Tamper with claims.** Decode the payload (it is Base64Url-encoded, not encrypted), modify claims such as `sub`, `role`, or `email`, re-sign or strip the signature, and replay the token. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **Check expiry enforcement.** Send a token whose `exp` claim is in the past. The server should return `401`; if it returns `200`, expiry is not being validated. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
| **Check expiry enforcement.** Send a token whose `exp` claim is in the past. The server should return `401`; if it returns `200`, expiry is not being validated. | |
| **Check expiry enforcement.** Send a token whose `exp` claim is in the past. The server should reject the request (commonly with `401` or `403`); if it returns `200`, expiry is not being validated. |
Copilot
AI
Apr 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to JWT expiry handling, out-of-scope OAuth2 requests are often rejected with 403, but some APIs use 401 or insufficient_scope error responses. Consider wording this as "should be rejected" and optionally mention 403 as a common outcome rather than a strict requirement.
| **Validate scope enforcement.** Obtain a token with a limited scope (e.g. `read:profile`) and attempt operations that require broader scope (e.g. `write:admin`). The server should reject out-of-scope requests with `403`. | |
| **Validate scope enforcement.** Obtain a token with a limited scope (e.g. `read:profile`) and attempt operations that require broader scope (e.g. `write:admin`). The server should reject out-of-scope requests, commonly with `403` or an `insufficient_scope` error response. |
Copilot
AI
Apr 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are common/de facto rate-limit headers, but calling them "standard" is inaccurate: X-RateLimit-* is non-standard, and there is also the standardized RateLimit-* header set (RFC 9239) used by some APIs. Suggest changing wording to "common"/"often used" and optionally adding RateLimit-Limit/Remaining/Reset alongside the X- variants.
| **Establish a baseline.** Send a sequence of identical requests and note response time, headers, and status codes. Look for standard rate-limiting headers: | |
| - `X-RateLimit-Limit` — the request ceiling | |
| - `X-RateLimit-Remaining` — requests remaining in the current window | |
| - `X-RateLimit-Reset` — Unix timestamp when the window resets | |
| **Establish a baseline.** Send a sequence of identical requests and note response time, headers, and status codes. Look for common rate-limiting headers such as: | |
| - `X-RateLimit-Limit` — common non-standard header for the request ceiling | |
| - `X-RateLimit-Remaining` — common non-standard header for requests remaining in the current window | |
| - `X-RateLimit-Reset` — common non-standard header for when the window resets | |
| - `RateLimit-Limit` — standardized header for the request ceiling | |
| - `RateLimit-Remaining` — standardized header for requests remaining in the current window | |
| - `RateLimit-Reset` — standardized header for when the window resets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sentence implies OpenAPI "replaces" WSDL and WADL, but WSDL is primarily a SOAP service description format (and the earlier section of this cheat sheet already frames WSDL in the SOAP context). To avoid factual inconsistency/misleading guidance, consider rephrasing to position OpenAPI as the de facto standard for REST API descriptions, contrasting mainly with older REST description proposals like WADL (and optionally noting that WSDL is typically for SOAP).