Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions cheatsheets/REST_Assessment_Cheat_Sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link

Copilot AI Apr 26, 2026

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).

Suggested change
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.
Modern REST APIs are commonly described using the [OpenAPI Specification (OAS)](https://www.openapis.org/), the de facto standard for REST API descriptions. It supersedes older REST description proposals such as WADL; WSDL is typically used for SOAP services. When an OpenAPI definition is available it significantly accelerates attack surface discovery.

Copilot uses AI. Check for mistakes.

**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.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The 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
header.payload. Some JWT libraries reject a token that is missing the final period entirely. The description should read:

▎ 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.
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all APIs respond with 401 specifically for an expired/invalid JWT (some use 403 or 400 depending on authn/authz handling). To keep the guidance accurate across implementations, consider changing this to "the server should reject the request" and optionally mention common status codes (401/403).

Suggested change
**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 uses AI. Check for mistakes.

**Inspect the payload for sensitive data.** JWT payloads are readable by anyone who holds the token. Look for PII, internal identifiers, or role information that should not be client-visible.

**Test `kid` header injection.** If the server resolves a signing key by a `kid` (key ID) header value, test for SQL injection, path traversal, and SSRF via that field.

For comprehensive JWT attack guidance see the [OWASP JSON Web Token Cheat Sheet](JSON_Web_Token_for_Java_Cheat_Sheet.md).

### OAuth2 Assessment

**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`.
Copy link

Copilot AI Apr 26, 2026

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.

Suggested change
**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 uses AI. Check for mistakes.

**Test token reuse across tenants.** In multi-tenant APIs, use a valid token issued to Tenant A and attempt to access resources belonging to Tenant B.

**Check PKCE enforcement.** For authorization code flows, confirm that [PKCE](https://oauth.net/2/pkce/) (`code_challenge` / `code_verifier`) is required. Without it, a stolen authorization code can be exchanged for a token.

**Attempt refresh token misuse.** Test whether refresh tokens can be used more than once (they should be rotated and invalidated on use) and whether they expire.

## Broken Object Level Authorization (BOLA)

[BOLA](https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/) (also known as IDOR — Insecure Direct Object Reference) is the most common API vulnerability in the [OWASP API Security Top 10](https://owasp.org/API-Security/).

**Identify object identifiers in requests.** Look for numeric IDs, UUIDs, slugs, or hashes in URL path segments and query parameters:

```
GET /api/v1/orders/4821
GET /api/v1/users/7/documents/99
```

**Horizontal privilege escalation.** Authenticate as User A, capture the identifier for one of User A's resources, then substitute the identifier for a resource belonging to User B. If the server returns User B's data, BOLA is present.

**Vertical privilege escalation.** Substitute identifiers for objects belonging to a higher-privilege user (e.g. an administrator record) using a low-privilege token.

**Test all HTTP methods.** An endpoint that correctly restricts `GET` on another user's resource may still permit `PUT`, `PATCH`, or `DELETE` on it.

**Test indirect references.** Some APIs replace direct database IDs with hashed or encoded identifiers. Attempt to decode or enumerate these — predictable schemes (sequential integers encoded in Base64, for example) can still be exploited.

## Mass Assignment in JSON APIs

Mass assignment occurs when an API automatically binds request body fields to internal object properties without filtering, allowing attackers to set fields the application never intended to expose — such as `role`, `isAdmin`, or `balance`.

**Identify bindable fields.** Compare the fields documented in the API schema against the fields present in the response body. Undocumented response fields are candidates for assignment testing.

**Inject extra fields in `POST` and `PUT` requests.** Add fields beyond those shown in the documentation:

```json
{
"name": "Alice",
"email": "alice@example.com",
"role": "admin",
"isVerified": true
}
```

Inspect the response and any subsequent `GET` requests for that resource to determine whether the injected fields were persisted.

**Target numeric privilege escalation fields.** Fields such as `credits`, `balance`, `quota`, or `subscriptionTier` are high-value targets. Attempt to set them to arbitrarily large values.

**Test `PATCH` separately.** Partial-update endpoints may apply mass assignment independently of full-update `PUT` endpoints.

## Rate Limiting and Throttling Assessment

APIs that do not enforce rate limits are vulnerable to credential stuffing, enumeration, denial-of-service, and scraping attacks.

**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
Comment on lines +164 to +168
Copy link

Copilot AI Apr 26, 2026

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.

Suggested change
**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

Copilot uses AI. Check for mistakes.
- `Retry-After` — seconds to wait after a `429` response

**Exceed the limit.** Send enough requests to exhaust the documented limit and confirm the API returns `429 Too Many Requests`. A `200` response after the limit is exceeded indicates rate limiting is not enforced.

**Test per-resource limits separately.** Authentication endpoints (login, password reset, OTP verification) should have stricter limits than general data endpoints. Test each independently.

**Attempt limit bypass.** Try the following bypass techniques and observe whether the limit resets or is circumvented:

- Rotating `X-Forwarded-For` or `X-Real-IP` header values.
- Distributing requests across multiple API keys or accounts.
- Using different HTTP methods (`GET` vs `POST`) for the same logical operation.

**Test for missing limits on sensitive operations.** Enumeration attacks against user IDs, coupon codes, OTPs, and similar finite spaces are often feasible even at low request rates if no limit is applied. Test these explicitly.

## Related Resources

- [REST Security Cheat Sheet](REST_Security_Cheat_Sheet.md) - the other side of this cheat sheet
- [OWASP API Security Top 10](https://owasp.org/API-Security/)
- [OWASP JSON Web Token Cheat Sheet](JSON_Web_Token_for_Java_Cheat_Sheet.md)
- [OWASP OAuth 2.0 Cheat Sheet](OAuth2_Cheat_Sheet.md)
- [Schemathesis — OpenAPI fuzzing tool](https://schemathesis.readthedocs.io/)
- [YouTube: RESTful services, web security blind spot](https://www.youtube.com/watch?v=pWq4qGLAZHI) - a video presentation elaborating on most of the topics on this cheat sheet.
Loading