FBpsLab is a small, containerized lab environment that demonstrates how 401 Unauthorized and 403 Forbidden controls can be bypassed when a reverse proxy (Nginx) and a backend (Flask) interpret or match requests differently.
It is intended for academic, training, and demonstrative purposes in controlled environments, and can be tested with FBps or similar tools that generate request variations (path, headers, methods, normalization quirks).
FBpsLab runs two main services via Docker Compose:
- Nginx: reverse proxy and access-control enforcement layer (intentionally misconfigured)
- Flask: backend application exposing endpoints used to verify whether a request reached the app
A simplified request flow:
+--------------------+ +------------------------+ +------------------+
| Client | HTTP | Nginx Reverse Proxy | HTTP | Flask Backend |
| (FBps, curl, etc.) | --------------> | (locations, auth, ACL) | --------------> | (app logic) |
| | 127.0.0.1:80 | | upstream :8000 | |
+--------------------+ +------------------------+ +------------------+
FBpsLab includes intentionally misconfigured scenarios that mirror real-world 401/403 bypass vulnerabilities:
- Location matching edge cases: prefix vs exact-match confusion, trailing slash handling
- Routing precedence issues: regex locations overriding prefix-based deny rules
- Unsafe header-based controls: access decisions based on client-controlled headers
- Normalization discrepancies: different path decoding/trimming between proxy and backend
- API versioning gaps: newer endpoints protected while legacy versions remain accessible
- Case-sensitivity mismatches: proxy matches case-sensitively but backend routes case-insensitively (or vice versa)
Backend endpoints return clear responses indicating whether the request was stopped at the proxy or successfully reached the application.
- Docker and Docker Compose installed
- Basic HTTP client (curl, browser, or FBps)
git clone https://github.com/Uglybeard/fbps-lab.git
cd fbps-labFrom the project root:
docker-compose up --buildThis starts:
- Nginx on port 80 (published as 80:80 on the host)
- Flask app on port 8000 (internal service port, reached via Nginx upstream)
This lab demonstrates common 401/403 bypass classes. Examples include:
- Path matching quirks:
/admin/blocked but/adminreaches the backend due to trailing slash differences hitting different Nginx locations - Exact-match gaps:
/private/requires auth but/private/index.htmlbypasses it when authentication applies only to the exact path - Location precedence:
/static/internal/usersblocked but/static/internal/users.jsonallowed when regex locations (e.g., matching.json) override prefix denies - Header-based bypasses:
/local/grants access whenX-Forwarded-For: 127.0.0.1is present,/user_agentallows specificUser-Agentvalues. Demonstrates risks of trusting client-controlled headers for authorization - API version downgrade:
/api/v2/secretsprotected but/api/v1/secretsremains accessible (legacy path forgotten in proxy rules)
A complete list of vulnerable endpoints with detailed descriptions is available at the root endpoint when the lab is running. This index page documents each vulnerability class, the expected behavior, and hints for exploitation.
FBpsLab is a deliberately insecure laboratory for educational use. Do NOT deploy it on exposed or production systems.
