first commit
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
---
|
||||
name: fastapi
|
||||
description: Security testing playbook for FastAPI applications covering ASGI, dependency injection, and API vulnerabilities
|
||||
---
|
||||
|
||||
# FastAPI
|
||||
|
||||
Security testing for FastAPI/Starlette applications. Focus on dependency injection flaws, middleware gaps, and authorization drift across routers and channels.
|
||||
|
||||
## Attack Surface
|
||||
|
||||
**Core Components**
|
||||
- ASGI middlewares: CORS, TrustedHost, ProxyHeaders, Session, exception handlers, lifespan events
|
||||
- Routers and sub-apps: APIRouter prefixes/tags, mounted apps (StaticFiles, admin), `include_router`, versioned paths
|
||||
- Dependency injection: `Depends`, `Security`, `OAuth2PasswordBearer`, `HTTPBearer`, scopes
|
||||
|
||||
**Data Handling**
|
||||
- Pydantic models: v1/v2, unions/Annotated, custom validators, extra fields policy, coercion
|
||||
- File operations: UploadFile, File, FileResponse, StaticFiles mounts
|
||||
- Templates: Jinja2Templates rendering
|
||||
|
||||
**Channels**
|
||||
- HTTP (sync/async), WebSocket, SSE/StreamingResponse
|
||||
- BackgroundTasks and task queues
|
||||
|
||||
**Deployment**
|
||||
- Uvicorn/Gunicorn, reverse proxies/CDN, TLS termination, header trust
|
||||
|
||||
## High-Value Targets
|
||||
|
||||
- `/openapi.json`, `/docs`, `/redoc` in production (full attack surface map, securitySchemes, server URLs)
|
||||
- Auth flows: token endpoints, session/cookie bridges, OAuth device/PKCE
|
||||
- Admin/staff routers, feature-flagged routes, `include_in_schema=False` endpoints
|
||||
- File upload/download, import/export/report endpoints, signed URL generators
|
||||
- WebSocket endpoints (notifications, admin channels, commands)
|
||||
- Background job endpoints (`/jobs/{id}`, `/tasks/{id}/result`)
|
||||
- Mounted subapps (admin UI, storage browsers, metrics/health)
|
||||
|
||||
## Reconnaissance
|
||||
|
||||
**OpenAPI Mining**
|
||||
```
|
||||
GET /openapi.json
|
||||
GET /docs
|
||||
GET /redoc
|
||||
GET /api/openapi.json
|
||||
GET /internal/openapi.json
|
||||
```
|
||||
|
||||
Extract: paths, parameters, securitySchemes, scopes, servers. Endpoints with `include_in_schema=False` won't appear—fuzz based on discovered prefixes and common admin/debug names.
|
||||
|
||||
**Dependency Mapping**
|
||||
|
||||
For each route, identify:
|
||||
- Router-level dependencies (applied to all routes)
|
||||
- Route-level dependencies (per endpoint)
|
||||
- Which dependencies enforce auth vs just parse input
|
||||
|
||||
## Key Vulnerabilities
|
||||
|
||||
### Authentication & Authorization
|
||||
|
||||
**Dependency Injection Gaps**
|
||||
- Routes missing security dependencies present on other routes
|
||||
- `Depends` used instead of `Security` (ignores scope enforcement)
|
||||
- Token presence treated as authentication without signature verification
|
||||
- `OAuth2PasswordBearer` only yields a token string—verify routes don't treat presence as auth
|
||||
|
||||
**JWT Misuse**
|
||||
- Decode without verify: test unsigned tokens, attacker-signed tokens
|
||||
- Algorithm confusion: HS256/RS256 cross-use if not pinned
|
||||
- `kid` header injection for custom key lookup paths
|
||||
- Missing issuer/audience validation, cross-service token reuse
|
||||
|
||||
**Session Weaknesses**
|
||||
- SessionMiddleware with weak `secret_key`
|
||||
- Session fixation via predictable signing
|
||||
- Cookie-based auth without CSRF protection
|
||||
|
||||
**OAuth/OIDC**
|
||||
- Device/PKCE flows: verify strict PKCE S256 and state/nonce enforcement
|
||||
|
||||
### Access Control
|
||||
|
||||
**IDOR via Dependencies**
|
||||
- Object IDs in path/query not validated against caller
|
||||
- Tenant headers trusted without binding to authenticated user
|
||||
- BackgroundTasks acting on IDs without re-validating ownership at execution time
|
||||
- Export/import pipelines with IDOR and cross-tenant leaks
|
||||
|
||||
**Scope Bypass**
|
||||
- Minimal scope satisfaction (any valid token accepted)
|
||||
- Router vs route scope enforcement inconsistency
|
||||
|
||||
### Input Handling
|
||||
|
||||
**Pydantic Exploitation**
|
||||
- Type coercion: strings to ints/bools, empty strings to None, truthiness edge cases
|
||||
- Extra fields: `extra = "allow"` permits injecting control fields (role, ownerId, scope)
|
||||
- Union types and `Annotated`: craft shapes hitting unintended validation branches
|
||||
|
||||
**Content-Type Switching**
|
||||
```
|
||||
application/json ↔ application/x-www-form-urlencoded ↔ multipart/form-data
|
||||
```
|
||||
Different content types hit different validators or code paths (parser differentials).
|
||||
|
||||
**Parameter Manipulation**
|
||||
- Case variations in header/cookie names
|
||||
- Duplicate parameters exploiting DI precedence
|
||||
- Method override via `X-HTTP-Method-Override` (upstream respects, app doesn't)
|
||||
|
||||
### CORS & CSRF
|
||||
|
||||
**CORS Misconfiguration**
|
||||
- Overly broad `allow_origin_regex`
|
||||
- Origin reflection without validation
|
||||
- Credentialed requests with permissive origins
|
||||
- Verify preflight vs actual request deltas
|
||||
|
||||
**CSRF Exposure**
|
||||
- No built-in CSRF in FastAPI/Starlette
|
||||
- Cookie-based auth without origin validation
|
||||
- Missing SameSite attribute
|
||||
|
||||
### Proxy & Host Trust
|
||||
|
||||
**Header Spoofing**
|
||||
- ProxyHeadersMiddleware without network boundary: spoof `X-Forwarded-For/Proto` to influence auth/IP gating
|
||||
- Absent TrustedHostMiddleware: Host header poisoning in password reset links, absolute URL generation
|
||||
- Cache key confusion: missing Vary on Authorization/Cookie/Tenant
|
||||
|
||||
### Server-Side Vulnerabilities
|
||||
|
||||
**Template Injection (Jinja2)**
|
||||
```python
|
||||
{{7*7}} # Arithmetic confirmation
|
||||
{{cycler.__init__.__globals__['os'].popen('id').read()}} # RCE
|
||||
```
|
||||
Check autoescape settings and custom filters/globals.
|
||||
|
||||
**SSRF**
|
||||
- User-supplied URLs in imports, previews, webhooks validation
|
||||
- Test: loopback, RFC1918, IPv6, redirects, DNS rebinding, header control
|
||||
- Library behavior (httpx/requests): redirect policy, header forwarding, protocol support
|
||||
- Protocol smuggling: `file://`, `ftp://`, gopher-like shims if custom clients
|
||||
|
||||
**File Upload**
|
||||
- Path traversal in `UploadFile.filename` with control characters
|
||||
- Missing storage root enforcement, symlink following
|
||||
- Vary filename encodings, dot segments, NUL-like bytes
|
||||
- Verify storage paths and served URLs
|
||||
|
||||
### WebSocket Security
|
||||
|
||||
- Missing per-connection authentication
|
||||
- Cross-origin WebSocket without origin validation
|
||||
- Topic/channel IDOR (subscribing to other users' channels)
|
||||
- Authorization only at handshake, not per-message
|
||||
|
||||
### Mounted Apps
|
||||
|
||||
Sub-apps at `/admin`, `/static`, `/metrics` may bypass global middlewares. Verify auth enforcement parity across all mounts.
|
||||
|
||||
### Alternative Stacks
|
||||
|
||||
- If GraphQL (Strawberry/Graphene) is mounted: validate resolver-level authorization, IDOR on node/global IDs
|
||||
- If SQLModel/SQLAlchemy present: probe for raw query usage and row-level authorization gaps
|
||||
|
||||
## Bypass Techniques
|
||||
|
||||
- Content-type switching to traverse alternate validators
|
||||
- Parameter duplication and case variants exploiting DI precedence
|
||||
- Method confusion via proxies (`X-HTTP-Method-Override`)
|
||||
- Race windows around dependency-validated state transitions (issue token then mutate with parallel requests)
|
||||
|
||||
## Testing Methodology
|
||||
|
||||
1. **Enumerate** - Fetch OpenAPI, diff with 404-fuzzing for hidden endpoints
|
||||
2. **Matrix testing** - Test each route across: unauth/user/admin × HTTP/WebSocket × JSON/form/multipart
|
||||
3. **Dependency analysis** - Map which dependencies enforce auth vs parse input
|
||||
4. **Cross-environment** - Compare dev/stage/prod for middleware and docs exposure differences
|
||||
5. **Channel consistency** - Verify same authorization on HTTP and WebSocket for equivalent operations
|
||||
|
||||
## Validation Requirements
|
||||
|
||||
- Side-by-side requests showing unauthorized access (owner vs non-owner, cross-tenant)
|
||||
- Cross-channel proof (HTTP and WebSocket for same rule)
|
||||
- Header/proxy manipulation showing altered outcomes (Host/XFF/CORS)
|
||||
- Minimal payloads for template injection, SSRF, token misuse with safe/OAST oracles
|
||||
- Document exact dependency paths (router-level, route-level) that missed enforcement
|
||||
@@ -0,0 +1,225 @@
|
||||
---
|
||||
name: nestjs
|
||||
description: Security testing playbook for NestJS applications covering guards, pipes, decorators, module boundaries, and multi-transport auth
|
||||
---
|
||||
|
||||
# NestJS
|
||||
|
||||
Security testing for NestJS applications. Focus on guard gaps across decorator stacks, validation pipe bypasses, module boundary leaks, and inconsistent auth enforcement across HTTP, WebSocket, and microservice transports.
|
||||
|
||||
## Attack Surface
|
||||
|
||||
**Decorator Pipeline**
|
||||
- Guards: `@UseGuards`, `CanActivate`, execution context (HTTP/WS/RPC), `Reflector` metadata
|
||||
- Pipes: `ValidationPipe` (whitelist, transform, forbidNonWhitelisted), `ParseIntPipe`, custom pipes
|
||||
- Interceptors: response mapping, caching, logging, timeout — can modify request/response flow
|
||||
- Filters: exception filters that may leak information
|
||||
- Metadata: `@SetMetadata`, `@Public()`, `@Roles()`, `@Permissions()`
|
||||
|
||||
**Module System**
|
||||
- `@Module` boundaries, provider scoping (DEFAULT/REQUEST/TRANSIENT)
|
||||
- Dynamic modules: `forRoot`/`forRootAsync`, global modules
|
||||
- DI container: provider overrides, custom providers
|
||||
|
||||
**Controllers & Transports**
|
||||
- REST: `@Controller`, versioning (URI/Header/MediaType)
|
||||
- GraphQL: `@Resolver`, playground/sandbox exposure
|
||||
- WebSocket: `@WebSocketGateway`, gateway guards, room authorization
|
||||
- Microservices: TCP, Redis, NATS, MQTT, gRPC, Kafka — often lack HTTP-level auth
|
||||
|
||||
**Data Layer**
|
||||
- TypeORM: repositories, QueryBuilder, raw queries, relations
|
||||
- Prisma: `$queryRaw`, `$queryRawUnsafe`
|
||||
- Mongoose: operator injection, `$where`, `$regex`
|
||||
|
||||
**Auth & Config**
|
||||
- `@nestjs/passport` strategies, `@nestjs/jwt`, session-based auth
|
||||
- `@nestjs/config`, ConfigService, `.env` files
|
||||
- `@nestjs/throttler`, rate limiting with `@SkipThrottle`
|
||||
|
||||
**API Documentation**
|
||||
- `@nestjs/swagger`: OpenAPI exposure, DTO schemas, auth schemes
|
||||
|
||||
## High-Value Targets
|
||||
|
||||
- Swagger/OpenAPI endpoints in production (`/api`, `/api-docs`, `/api-json`, `/swagger`)
|
||||
- Auth endpoints: login, register, token refresh, password reset, OAuth callbacks
|
||||
- Admin controllers decorated with `@Roles('admin')` — test with user-level tokens
|
||||
- File upload endpoints using `FileInterceptor`/`FilesInterceptor`
|
||||
- WebSocket gateways sharing business logic with HTTP controllers
|
||||
- Microservice handlers (`@MessagePattern`, `@EventPattern`) — often unguarded
|
||||
- CRUD generators (`@nestjsx/crud`) with auto-generated endpoints
|
||||
- Background jobs and scheduled tasks (`@nestjs/schedule`)
|
||||
- Health/metrics endpoints (`@nestjs/terminus`, `/health`, `/metrics`)
|
||||
- GraphQL playground/sandbox in production (`/graphql`)
|
||||
|
||||
## Reconnaissance
|
||||
|
||||
**Swagger Discovery**
|
||||
```
|
||||
GET /api
|
||||
GET /api-docs
|
||||
GET /api-json
|
||||
GET /swagger
|
||||
GET /docs
|
||||
GET /v1/api-docs
|
||||
GET /api/v2/docs
|
||||
```
|
||||
|
||||
Extract: paths, parameter schemas, DTOs, auth schemes, example values. Swagger may reveal internal endpoints, deprecated routes, and admin-only paths not visible in the UI.
|
||||
|
||||
**Guard Mapping**
|
||||
|
||||
For each controller and method, identify:
|
||||
- Global guards (applied in `main.ts` or app module)
|
||||
- Controller-level guards (`@UseGuards` on the class)
|
||||
- Method-level guards (`@UseGuards` on individual handlers)
|
||||
- `@Public()` or `@SkipThrottle()` decorators that bypass protection
|
||||
|
||||
## Key Vulnerabilities
|
||||
|
||||
### Guard Bypass
|
||||
|
||||
**Decorator Stack Gaps**
|
||||
- Guards execute: global → controller → method. A method missing `@UseGuards` when siblings have it is the #1 finding.
|
||||
- `@Public()` metadata causing global `AuthGuard` to skip enforcement — check if applied too broadly.
|
||||
- New methods added to existing controllers without inheriting the expected guard.
|
||||
|
||||
**ExecutionContext Switching**
|
||||
- Guards handling only HTTP context (`getRequest()`) may fail silently on WebSocket or RPC, returning `true` by default.
|
||||
- Test same business logic through alternate transports to find context-specific bypasses.
|
||||
|
||||
**Reflector Mismatches**
|
||||
- Guard reads `SetMetadata('roles', [...])` but decorator sets `'role'` (singular) — guard sees no metadata, defaults to allow.
|
||||
- `applyDecorators()` compositions accidentally overriding stricter guards with permissive ones.
|
||||
|
||||
### Validation Pipe Exploits
|
||||
|
||||
**Whitelist Bypass**
|
||||
- `whitelist: true` without `forbidNonWhitelisted: true`: extra properties silently stripped but may have been processed by earlier middleware/interceptors.
|
||||
- Missing `@Type(() => ChildDto)` on nested objects: `@ValidateNested()` without `@Type` means nested payload is never validated.
|
||||
- Array elements: `@IsArray()` doesn't validate elements without `@ValidateNested({ each: true })` and `@Type`.
|
||||
|
||||
**Type Coercion**
|
||||
- `transform: true` enables implicit coercion: strings → numbers, `"true"` → `true`, `"null"` → `null`.
|
||||
- Exploit truthiness assumptions in business logic downstream.
|
||||
|
||||
**Conditional Validation**
|
||||
- `@ValidateIf()` and validation groups creating paths where fields skip validation entirely.
|
||||
|
||||
**Missing Parse Pipes**
|
||||
- `@Param('id')` without `ParseIntPipe`/`ParseUUIDPipe` — string values reach ORM queries directly.
|
||||
|
||||
### Auth & Passport
|
||||
|
||||
**JWT Strategy**
|
||||
- Check `ignoreExpiration` is false, `algorithms` is pinned (no `none` or HS/RS confusion)
|
||||
- Weak `secretOrKey` values
|
||||
- Cross-service token reuse when audience/issuer not enforced
|
||||
|
||||
**Passport Strategy Issues**
|
||||
- `validate()` return value becomes `req.user` — if it returns full DB record, sensitive fields leak downstream
|
||||
- Multiple strategies (JWT + session): one may bypass restrictions of the other
|
||||
- Custom guards returning `true` for unauthenticated as "optional auth"
|
||||
|
||||
**Timing Attacks**
|
||||
- Plain string comparison instead of bcrypt/argon2 in local strategy
|
||||
|
||||
### Serialization Leaks
|
||||
|
||||
**Missing ClassSerializerInterceptor**
|
||||
- If not applied globally, `@Exclude()` fields (passwords, internal IDs) returned in responses.
|
||||
- `@Expose()` with groups: admin-only fields exposed when groups not enforced per-request.
|
||||
|
||||
**Circular Relations**
|
||||
- Eager-loaded TypeORM/Prisma relations exposing entire object graph without careful serialization.
|
||||
|
||||
### Interceptor Abuse
|
||||
|
||||
**Cache Poisoning**
|
||||
- `CacheInterceptor` without user/tenant identity in cache key — responses from one user served to another.
|
||||
- Test: authenticated request, then unauthenticated request returning cached data.
|
||||
|
||||
**Response Mapping**
|
||||
- Transformation interceptors may leak internal entity fields if mapping is incomplete.
|
||||
|
||||
### Module Boundary Leaks
|
||||
|
||||
**Global Module Exposure**
|
||||
- `@Global()` modules expose all providers to every module without explicit imports.
|
||||
- Sensitive services (admin operations, internal APIs) accessible from untrusted modules.
|
||||
|
||||
**Config Leaks**
|
||||
- `forRoot`/`forRootAsync` configuration secrets accessible via `ConfigService` injection in any module.
|
||||
|
||||
**Scope Issues**
|
||||
- Request-scoped providers (`Scope.REQUEST`) incorrectly scoped as DEFAULT (singleton) — request context leaks across concurrent requests.
|
||||
|
||||
### WebSocket Gateway
|
||||
|
||||
- HTTP guards don't automatically apply to WebSocket gateways — `@UseGuards` must be explicit.
|
||||
- Authentication deferred from `handleConnection` to message handlers allows unauthenticated message sending.
|
||||
- Room/namespace authorization: users joining rooms they shouldn't access.
|
||||
- `@SubscribeMessage()` handlers relying on connection-level auth instead of per-message validation.
|
||||
|
||||
### Microservice Transport
|
||||
|
||||
- `@MessagePattern`/`@EventPattern` handlers often lack guards (considered "internal").
|
||||
- If transport (Redis, NATS, Kafka) is network-accessible, messages can be injected bypassing all HTTP security.
|
||||
- `ValidationPipe` may only be configured for HTTP — microservice payloads skip validation.
|
||||
|
||||
### ORM Injection
|
||||
|
||||
**TypeORM**
|
||||
- `QueryBuilder` and `.query()` with template literal interpolation → SQL injection.
|
||||
- Relations: API allowing specification of which relations to load via query params.
|
||||
|
||||
**Mongoose**
|
||||
- Query operator injection: `{ password: { $gt: "" } }` via unsanitized request body.
|
||||
- `$where` and `$regex` operators from user input.
|
||||
|
||||
**Prisma**
|
||||
- `$queryRaw`/`$executeRaw` with string interpolation (but not tagged template).
|
||||
- `$queryRawUnsafe` usage.
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
- `@SkipThrottle()` on sensitive endpoints (login, password reset, OTP).
|
||||
- In-memory throttler storage: resets on restart, doesn't work across instances.
|
||||
- Behind proxy without `trust proxy`: all requests share same IP, or header spoofable.
|
||||
|
||||
### CRUD Generators
|
||||
|
||||
- Auto-generated CRUD endpoints may not inherit manual guard configurations.
|
||||
- Bulk operations (`createMany`, `updateMany`) bypassing per-entity authorization.
|
||||
- Query parameter injection in CRUD libraries: `filter`, `sort`, `join`, `select` exposing unauthorized data.
|
||||
|
||||
## Bypass Techniques
|
||||
|
||||
- `@Public()` / skip-metadata applied via composed decorators at method level causing global guards to skip via `Reflector` metadata checks
|
||||
- Route param pollution: `/users/123?id=456` — which `id` wins in guards vs handlers?
|
||||
- Version routing: v1 of endpoint may still be registered without the guard added to v2
|
||||
- `X-HTTP-Method-Override` or `_method` processed by Express before guards
|
||||
- Content-type switching: `application/x-www-form-urlencoded` instead of JSON to bypass JSON-specific validation
|
||||
- Exception filter differences: guard throwing results in generic error that leaks route existence info
|
||||
|
||||
## Testing Methodology
|
||||
|
||||
1. **Enumerate** — Fetch Swagger/OpenAPI, map all controllers, resolvers, and gateways
|
||||
2. **Guard audit** — Map decorator stack per method: which guards, pipes, interceptors are applied at each level
|
||||
3. **Matrix testing** — Test each endpoint across: unauth/user/admin × HTTP/WS/microservice
|
||||
4. **Validation probing** — Send extra fields, wrong types, nested objects, arrays to find pipe gaps
|
||||
5. **Transport parity** — Same operation via HTTP, WebSocket, and microservice transport
|
||||
6. **Module boundaries** — Check if providers from one module are accessible without proper imports
|
||||
7. **Serialization check** — Compare raw entity fields with API response fields
|
||||
|
||||
## Validation Requirements
|
||||
|
||||
- Guard bypass: request to guarded endpoint succeeding without auth, showing guard chain break point
|
||||
- Validation bypass: payload with extra/malformed fields affecting business logic
|
||||
- Cross-transport inconsistency: same action authorized via HTTP but exploitable via WebSocket/microservice
|
||||
- Module boundary leak: accessing provider or data across unauthorized module boundaries
|
||||
- Serialization leak: response containing excluded fields (passwords, internal metadata)
|
||||
- IDOR: side-by-side requests from different users showing unauthorized data access
|
||||
- ORM injection: raw query with user-controlled input returning unauthorized data, or error-based evidence of query structure
|
||||
- Cache poisoning: response from unauthenticated or different-user request matching a prior authenticated user's cached response
|
||||
@@ -0,0 +1,228 @@
|
||||
---
|
||||
name: nextjs
|
||||
description: Security testing playbook for Next.js covering App Router, Server Actions, RSC, and Edge runtime vulnerabilities
|
||||
---
|
||||
|
||||
# Next.js
|
||||
|
||||
Security testing for Next.js applications. Focus on authorization drift across runtimes (Edge/Node), caching boundaries, server actions, and middleware bypass.
|
||||
|
||||
## Attack Surface
|
||||
|
||||
**Routers**
|
||||
- App Router (`app/`) and Pages Router (`pages/`) often coexist
|
||||
- Route Handlers (`app/api/**`) and API routes (`pages/api/**`)
|
||||
- Middleware: `middleware.ts` at project root
|
||||
|
||||
**Runtimes**
|
||||
- Node.js (full API access)
|
||||
- Edge (V8 isolates, restricted APIs)
|
||||
|
||||
**Rendering & Caching**
|
||||
- SSR, SSG, ISR, on-demand revalidation
|
||||
- RSC (React Server Components) with fetch cache
|
||||
- Draft/preview mode
|
||||
|
||||
**Data Paths**
|
||||
- Server Components, Client Components
|
||||
- Server Actions (streamed POST with `Next-Action` header)
|
||||
- `getServerSideProps`, `getStaticProps`
|
||||
|
||||
**Integrations**
|
||||
- NextAuth.js (callbacks, CSRF, callbackUrl)
|
||||
- `next/image` optimization and remote loaders
|
||||
|
||||
## High-Value Targets
|
||||
|
||||
- Middleware-protected routes (auth, geo, A/B)
|
||||
- Admin/staff paths, draft/preview content, on-demand revalidate endpoints
|
||||
- RSC payloads and flight data, streamed responses
|
||||
- Image optimizer and custom loaders, remotePatterns/domains
|
||||
- NextAuth callbacks (`/api/auth/callback/*`), sign-in providers
|
||||
- Edge-only features (bot protection, IP gates) and their Node equivalents
|
||||
|
||||
## Reconnaissance
|
||||
|
||||
**Route Discovery**
|
||||
|
||||
```javascript
|
||||
// Browser console - list all routes
|
||||
console.log(__BUILD_MANIFEST.sortedPages.join('\n'))
|
||||
|
||||
// Inspect server-fetched data
|
||||
JSON.parse(document.getElementById('__NEXT_DATA__').textContent).props.pageProps
|
||||
|
||||
// List public environment variables
|
||||
Object.keys(process.env).filter(k => k.startsWith('NEXT_PUBLIC_'))
|
||||
```
|
||||
|
||||
**Build Artifacts**
|
||||
```
|
||||
GET /_next/static/<buildId>/_buildManifest.js
|
||||
GET /_next/static/<buildId>/_ssgManifest.js
|
||||
GET /_next/static/chunks/pages/
|
||||
GET /_next/static/chunks/app/
|
||||
```
|
||||
Chunk filenames map to routes (e.g., `admin.js` → `/admin`).
|
||||
|
||||
**Source Maps**
|
||||
|
||||
Check `/_next/static/` for exposed `.map` files revealing route structure, server action IDs, and internal functions.
|
||||
|
||||
**Client Bundle Mining**
|
||||
|
||||
Search main-*.js for: `pathname:`, `href:`, `__next_route__`, `serverActions`, API endpoints. Grep for `API_KEY`, `SECRET`, `TOKEN`, `PASSWORD` to find accidentally leaked credentials.
|
||||
|
||||
**Server Action Discovery**
|
||||
|
||||
Inspect Network tab for POST requests with `Next-Action` header. Extract action IDs from response streams and hydration data.
|
||||
|
||||
**Additional Leakage**
|
||||
- `/sitemap.xml`, `/robots.txt`, `/sitemap-*.xml` for unintended admin/internal/preview paths
|
||||
- Client bundles/env for secret paths and preview/admin flags (many teams hide routes via UI only)
|
||||
|
||||
## Key Vulnerabilities
|
||||
|
||||
### Middleware Bypass
|
||||
|
||||
**Known Techniques**
|
||||
- `x-middleware-subrequest` header crafting (CVE-class bypass)
|
||||
- `x-nextjs-data` probing
|
||||
- Look for 307 + `x-middleware-rewrite`/`x-nextjs-redirect` headers
|
||||
|
||||
**Path Normalization**
|
||||
```
|
||||
/api/users
|
||||
/api/users/
|
||||
/api//users
|
||||
/api/./users
|
||||
```
|
||||
Middleware may normalize differently than route handlers. Test double slashes, trailing slashes, dot segments.
|
||||
|
||||
**Parameter Pollution**
|
||||
```
|
||||
?id=1&id=2
|
||||
?filter[]=a&filter[]=b
|
||||
```
|
||||
Middleware checks first value, handler uses last or array.
|
||||
|
||||
### Server Actions
|
||||
|
||||
- Invoke actions outside UI flow with alternate content-types
|
||||
- Authorization assumed from client state rather than enforced server-side
|
||||
- IDOR via object references in action payloads
|
||||
- Map action IDs from source maps to discover hidden actions
|
||||
|
||||
### RSC & Caching
|
||||
|
||||
**Cache Boundary Failures**
|
||||
- User-bound data cached without identity keys (ETag/Set-Cookie unaware)
|
||||
- Personalized content served from shared cache/CDN
|
||||
- Missing `no-store` on sensitive fetches
|
||||
|
||||
**Flight Data Leakage**
|
||||
|
||||
Inspect streamed RSC payloads for serialized sensitive fields in props.
|
||||
|
||||
**ISR Issues**
|
||||
- Stale-while-revalidate responses containing user-specific or tenant-dependent data
|
||||
- Weak secrets in on-demand revalidation endpoint URLs
|
||||
- Referer-disclosed tokens or unvalidated hosts triggering `revalidatePath`/`revalidateTag`
|
||||
- Header-smuggling or method variations to trigger revalidation
|
||||
|
||||
### Authentication
|
||||
|
||||
**NextAuth Pitfalls**
|
||||
- Missing/relaxed state/nonce/PKCE per provider (login CSRF, token mix-up)
|
||||
- Open redirect in `callbackUrl` or mis-scoped allowed hosts
|
||||
- JWT audience/issuer not enforced across routes
|
||||
- Cross-service token reuse
|
||||
- Session hijacking by forcing callbacks
|
||||
|
||||
**Session Boundaries**
|
||||
- Different auth enforcement between App Router and Pages Router
|
||||
- API routes vs Route Handlers authorization inconsistency
|
||||
|
||||
### Data Exposure
|
||||
|
||||
**__NEXT_DATA__ Over-fetching**
|
||||
|
||||
Server-fetched data passed to client but not rendered:
|
||||
- Full user objects when only username needed
|
||||
- Internal IDs, tokens, admin-only fields
|
||||
- ORM select-all patterns exposing entire records
|
||||
- API responses forwarded without sanitization (metadata, cursors, debug info)
|
||||
|
||||
**Environment-Dependent Exposure**
|
||||
- Staging/dev accidentally exposes more fields than production
|
||||
- Inconsistent serialization logic across environments
|
||||
|
||||
**Props Inspection**
|
||||
```javascript
|
||||
// Check for sensitive data in page props
|
||||
JSON.parse(document.getElementById('__NEXT_DATA__').textContent).props
|
||||
```
|
||||
Look for `_metadata`, `_internal`, `__typename` (GraphQL), nested sensitive objects.
|
||||
|
||||
### Image Optimizer SSRF
|
||||
|
||||
**Remote Patterns**
|
||||
- Broad `images.domains`/`remotePatterns` in `next.config.js`
|
||||
- Test: internal hosts, IPv4/IPv6 variants, DNS rebinding
|
||||
|
||||
**Custom Loaders**
|
||||
- Protocol smuggling via redirect chains
|
||||
- Cache poisoning via URL normalization differences affecting other users
|
||||
|
||||
### Runtime Divergence
|
||||
|
||||
**Edge vs Node**
|
||||
- Defenses relying on Node-only modules skipped on Edge
|
||||
- Header trust differs (`x-forwarded-*` handling)
|
||||
- Same route may behave differently across runtimes
|
||||
|
||||
### Client-Side
|
||||
|
||||
**XSS Vectors**
|
||||
- `dangerouslySetInnerHTML`
|
||||
- Markdown renderers
|
||||
- User-controlled href/src attributes
|
||||
- Validate CSP/Trusted Types coverage for SSR/CSR/hydration
|
||||
|
||||
**Hydration Mismatches**
|
||||
|
||||
Server vs client render differences can enable gadget-based XSS.
|
||||
|
||||
### Draft/Preview Mode
|
||||
|
||||
- Secret URLs/cookies enabling preview
|
||||
- Preview secrets leaked in client bundles/env
|
||||
- Setting preview cookies from subdomains or via open redirects
|
||||
|
||||
## Bypass Techniques
|
||||
|
||||
- Content-type switching: `application/json` ↔ `multipart/form-data` ↔ `application/x-www-form-urlencoded`
|
||||
- Method override: `_method`, `X-HTTP-Method-Override`, GET on endpoints accepting writes
|
||||
- Case/param aliasing and query duplication affecting middleware vs handler parsing
|
||||
- Cache key confusion at CDN/proxy (lack of Vary on auth cookies/headers)
|
||||
|
||||
## Testing Methodology
|
||||
|
||||
1. **Enumerate** - Use `__BUILD_MANIFEST`, source maps, build artifacts, sitemap/robots to map all routes
|
||||
2. **Runtime matrix** - Test each route under Edge and Node runtimes
|
||||
3. **Role matrix** - Test as unauth/user/admin across SSR, API routes, Route Handlers, Server Actions
|
||||
4. **Cache probing** - Verify caching respects identity (strip cookies, alter Vary headers, check ETags)
|
||||
5. **Middleware validation** - Test path variants and header manipulation for bypass
|
||||
6. **Cross-router** - Compare authorization between App Router and Pages Router paths
|
||||
|
||||
## Validation Requirements
|
||||
|
||||
- Side-by-side requests showing cross-user/tenant access
|
||||
- Cache boundary failure proof (response diffs, ETag collisions)
|
||||
- Server action invocation outside UI with insufficient auth
|
||||
- Middleware bypass with explicit headers showing protected content access
|
||||
- Runtime parity checks (Edge vs Node inconsistent enforcement)
|
||||
- Discovered routes verified as deployed (200/403) not just build artifacts (404)
|
||||
- Leaked credentials tested with minimal read-only calls; filter placeholders
|
||||
- `__NEXT_DATA__` exposure: verify cross-user (User A's props shouldn't contain User B's PII), confirm exposed fields not in DOM
|
||||
- Path normalization bypasses: show differential responses (403 vs 200), redirects don't count
|
||||
Reference in New Issue
Block a user