Web Interfaces
Authentication Forms
Protected Pages
- Basic Auth Required
- Session Required (logged_in: true)
- 2FA Session Required (2fa_logged_in: true)
- Secret Header Required
- Secret Cookie Required
Vulnerable Tools
OAuth2 Testing Guide
This lab implements two OAuth2 grant types: Authorization Code (user login via browser + API token exchange) and Client Credentials (pure API, machine-to-machine, no user involved). Multiple intentional vulnerabilities are present for pentest practice.
How the Authorization Code Flow Works
How Client Credentials Works (API-only)
No browser, no user, no redirects. The application authenticates as itself with a single API call and gets a token back. Used for machine-to-machine communication.
Try it: Client Credentials (curl)
# Step 1: Get a token with client credentials curl -X POST http://localhost:5000/api/v1/oauth2/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "client_credentials", "client_id": "vulapp-client-001", "client_secret": "super-secret-client-secret", "scope": "read profile" }' # Response: # { # "access_token": "a1b2c3d4e5f6...", # "token_type": "Bearer", # "expires_in": 3600, # "scope": "read profile" # }
# Step 2: Use the token to access protected resources curl http://localhost:5000/api/v1/oauth2/userinfo \ -H "Authorization: Bearer <ACCESS_TOKEN>" # Response: # { # "sub": "service-account-vulapp-client-001", # "username": "service-account-vulapp-client-001", # "email": "service-account-vulapp-client-001@vulapp.local", # "scope": "read profile" # }
# Try it: request any scope you want (vulnerability #7)
curl -X POST http://localhost:5000/api/v1/oauth2/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "vulapp-client-001",
"client_secret": "super-secret-client-secret",
"scope": "admin write delete"
}'
OAuth2 Endpoints
| Endpoint | Method | Type | Description |
|---|---|---|---|
| /web/oauth2/login | GET | Web | Landing page with flow overview |
| /web/oauth2/authorize | GET/POST | Web | Authorization + consent screen |
| /web/oauth2/callback | GET | Web | Receives auth code, interactive token exchange |
| /web/oauth2/profile | GET | Web | Protected resource (Bearer token or ?token=) |
| /api/v1/oauth2/token | POST | API | Token endpoint (authorization_code + client_credentials) |
| /api/v1/oauth2/userinfo | GET | API | User profile (requires Bearer token) |
Try it: Authorization Code (curl)
After completing steps 1-3 in the browser above, copy the authorization code from the callback URL and run:
# Step 4: Exchange the authorization code for an access token curl -X POST http://localhost:5000/api/v1/oauth2/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "authorization_code", "code": "<AUTH_CODE_FROM_STEP_3>", "client_id": "vulapp-client-001", "client_secret": "super-secret-client-secret", "redirect_uri": "/web/oauth2/callback" }' # Response: # { # "access_token": "a1b2c3d4e5f6...", # "token_type": "Bearer", # "expires_in": 3600, # "scope": "read profile" # }
# Step 5: Use the token to access protected resources curl http://localhost:5000/api/v1/oauth2/userinfo \ -H "Authorization: Bearer <ACCESS_TOKEN>" # Response: # { # "sub": "admin", # "username": "admin", # "email": "admin@vulapp.local", # "scope": "read profile" # }
Intentional Vulnerabilities
-
1
Open Redirect —
redirect_uriis never validated. An attacker can change it to any URL to steal authorization codes. -
2
No CSRF Protection — The
stateparameter is passed through but never validated server-side. - 3 Auth Code Replay — Authorization codes are not invalidated after use and can be exchanged for tokens multiple times.
-
4
No Client Secret Validation — The token endpoint accepts any value (or none) for
client_secret. -
5
Token in Query String —
/web/oauth2/profile?token=...is accepted, leaking tokens in logs and Referer headers. - 6 Predictable Auth Codes — Codes are generated with MD5(username + timestamp), making them guessable.
-
7
Unrestricted Scopes (Client Credentials) — The client_credentials grant accepts any
scopevalue without validation. Requestadminorwrite deleteand it will be granted.