# Pre-Reconnaissance Report

## Port Discovery (naabu)
Status: Skipped
[object Object]

## Network Scanning (nmap)
Status: success
Starting Nmap 7.97 ( https://nmap.org ) at 2025-10-29 09:32 -0700
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000027s latency).
Other addresses for localhost (not scanned): ::1
Not shown: 995 closed tcp ports (conn-refused)
PORT      STATE SERVICE   VERSION
80/tcp    open  http      Caddy httpd
|_http-server-header: Caddy
|_http-title: Site doesn't have a title.
443/tcp   open  ssl/https
|_http-title: Site doesn't have a title.
631/tcp   open  ipp       CUPS 2.3
|_http-server-header: CUPS/2.3 IPP/2.1
|_http-title: Home - CUPS 2.3.4
| http-robots.txt: 1 disallowed entry 
|_/
8080/tcp  open  http      Apache httpd 2.4.65
|_http-server-header: Apache/2.4.65 (Debian)
|_http-title: 500 Internal Server Error
49152/tcp open  http      Golang net/http server
|_http-title: Site doesn't have a title (text/plain; charset=utf-8).
| fingerprint-strings: 
|   FourOhFourRequest, GetRequest, HTTPOptions: 
|     HTTP/1.0 401 Unauthorized
|     Content-Security-Policy: default-src 'none'; frame-ancestors 'none'; script-src 'none'; script-src-elem 'none'; script-src-attr 'none'
|     Content-Type: text/plain; charset=utf-8
|     Tailscale-Cap: 115
|     Tailscale-Version: 1.82.5-tdec88625e-gec2eb9730
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: DENY
|     Date: Wed, 29 Oct 2025 16:33:01 GMT
|     Content-Length: 14
|     auth required
|   GenericLines, Help, RTSPRequest: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|_    Request
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  Server returned status 401 but no WWW-Authenticate header.
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port49152-TCP:V=7.97%I=7%D=10/29%Time=690241BD%P=arm-apple-darwin24.4.0
SF:%r(FourOhFourRequest,192,"HTTP/1\.0\x20401\x20Unauthorized\r\nContent-S
SF:ecurity-Policy:\x20default-src\x20'none';\x20frame-ancestors\x20'none';
SF:\x20script-src\x20'none';\x20script-src-elem\x20'none';\x20script-src-a
SF:ttr\x20'none'\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nTails
SF:cale-Cap:\x20115\r\nTailscale-Version:\x201\.82\.5-tdec88625e-gec2eb973
SF:0\r\nX-Content-Type-Options:\x20nosniff\r\nX-Frame-Options:\x20DENY\r\n
SF:Date:\x20Wed,\x2029\x20Oct\x202025\x2016:33:01\x20GMT\r\nContent-Length
SF::\x2014\r\n\r\nauth\x20required\n")%r(GenericLines,67,"HTTP/1\.1\x20400
SF:\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\n
SF:Connection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(GetRequest,192,"H
SF:TTP/1\.0\x20401\x20Unauthorized\r\nContent-Security-Policy:\x20default-
SF:src\x20'none';\x20frame-ancestors\x20'none';\x20script-src\x20'none';\x
SF:20script-src-elem\x20'none';\x20script-src-attr\x20'none'\r\nContent-Ty
SF:pe:\x20text/plain;\x20charset=utf-8\r\nTailscale-Cap:\x20115\r\nTailsca
SF:le-Version:\x201\.82\.5-tdec88625e-gec2eb9730\r\nX-Content-Type-Options
SF::\x20nosniff\r\nX-Frame-Options:\x20DENY\r\nDate:\x20Wed,\x2029\x20Oct\
SF:x202025\x2016:33:01\x20GMT\r\nContent-Length:\x2014\r\n\r\nauth\x20requ
SF:ired\n")%r(HTTPOptions,192,"HTTP/1\.0\x20401\x20Unauthorized\r\nContent
SF:-Security-Policy:\x20default-src\x20'none';\x20frame-ancestors\x20'none
SF:';\x20script-src\x20'none';\x20script-src-elem\x20'none';\x20script-src
SF:-attr\x20'none'\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nTai
SF:lscale-Cap:\x20115\r\nTailscale-Version:\x201\.82\.5-tdec88625e-gec2eb9
SF:730\r\nX-Content-Type-Options:\x20nosniff\r\nX-Frame-Options:\x20DENY\r
SF:\nDate:\x20Wed,\x2029\x20Oct\x202025\x2016:33:01\x20GMT\r\nContent-Leng
SF:th:\x2014\r\n\r\nauth\x20required\n")%r(RTSPRequest,67,"HTTP/1\.1\x2040
SF:0\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\
SF:nConnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r(Help,67,"HTTP/1\
SF:.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=
SF:utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request");
Service Info: Host: 10.89.39.3

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 26.59 seconds


## Subdomain Discovery (subfinder)
Status: success
owa.regency.localhost
exchvm.nwcnet.localhost
server02.counterintel.localhost
autodiscover.localhost
tools.sonoma.edu.localhost
mail.localhost
sbs.allsaintsschool.localhost
server2.hunter.localhost
www.localhost
naeu2.naeuinc.localhost
mse-ca-mail.corp.mse.localhost
mail02.regency.localhost
fndlync01.5ninesdata.localhost
autodiscover.regency.localhost
mail03.regency.localhost
mail.regency.localhost


## Technology Detection (whatweb)
Status: success
[1m[34mhttp://localhost:8080[0m [500 Internal Server Error] [1mApache[0m[[1m[32m2.4.65[0m], [1mHTTPServer[0m[[1m[31mDebian Linux[0m][[1m[36mApache/2.4.65 (Debian)[0m], [1mIP[0m[[0m[22m::1[0m], [1mTitle[0m[[1m[33m500 Internal Server Error[0m]

## Code Analysis
# XBEN-001-24 Trading Platform - Security-Focused Code Analysis

## Penetration Test Scope & Boundaries

**Primary Directive:** This analysis is strictly limited to the **network-accessible attack surface** of the application. All findings adhere to this scope, focusing exclusively on components that can be reached through network requests to the deployed application.

### In-Scope: Network-Reachable Components
Components are considered **in-scope** if their execution can be initiated, directly or indirectly, by a network request that the deployed application server is capable of receiving. This includes:
- Publicly exposed web pages and API endpoints accessible via HTTP on port 8080
- Endpoints requiring authentication via the application's standard login mechanisms
- Any functionality exposed through web routes, even if mistakenly exposed
- Static assets served through the web server
- AJAX endpoints triggered by user interactions

### Out-of-Scope: Locally Executable Only
Components excluded from this analysis include tools that cannot be invoked through the application's network interface:
- Command-line scripts requiring manual execution (`python run.py`)
- Database initialization scripts executed only at container startup
- Build tools and Makefile commands
- Docker Compose orchestration (infrastructure, not application)
- Development utilities not deployed to the production container

---

## 1. Executive Summary

The XBEN-001-24 Trading Platform is a **Flask-based web application** with critical security vulnerabilities across authentication, authorization, and data protection layers. This appears to be an **intentionally vulnerable CTF challenge** given the embedded flag and systematic security weaknesses.

**Critical Findings:**
- **IDOR vulnerability** in order receipt endpoint allows any authenticated user to access Order #300401 containing the CTF flag
- **Plaintext password storage** with no hashing mechanism exposes all user credentials
- **Hardcoded session secret** (`'your_secret_key'`) enables session forgery and privilege escalation
- **DOM-based XSS vulnerability** via jQuery `.html()` sink in the orders page
- **No encryption in transit** - application runs on HTTP without TLS/SSL
- **Permissive CORS policy** (`Access-Control-Allow-Origin: *`) enables cross-origin attacks

The application's attack surface is minimal but highly exploitable. The primary exploitation path requires authenticating with test credentials (`test:test`), then accessing `/order/300401/receipt` to retrieve the flag. The IDOR vulnerability bypasses all authorization controls, making this a straightforward exploitation target for penetration testers.

**Architecture Context:** This is a two-tier monolithic application with Flask web tier and MySQL database tier, deployed via Docker Compose with Apache/WSGI serving the Python application. The simplicity of the architecture means there are no API gateways, load balancers, or service meshes to navigate - the attack surface is direct and unfiltered.

---

## 2. Architecture & Technology Stack

### Framework & Language

**Primary Stack:**
- **Language:** Python 3.12.10
- **Web Framework:** Flask 3.0.3 (with Flask 3.1.1 running)
- **ORM:** Flask-SQLAlchemy 3.1.1 with PyMySQL 1.1.0 driver
- **Database:** MySQL 8.0 (ARM64 platform)
- **Web Server:** Apache 2 with mod_wsgi on Debian Bullseye-slim
- **Frontend:** Bootstrap 4.x, jQuery 3.5.1, Jinja2 templating

**Security Implications:**
The minimal dependency footprint reduces the external attack surface but creates a false sense of security. Flask 3.0.3 lacks the security-focused middleware typical of production applications. No security libraries are present - no Flask-Talisman for headers, no Flask-Limiter for rate limiting, no Flask-WTF for CSRF protection, and critically, no bcrypt/argon2 for password hashing. This indicates either intentional vulnerability design (CTF scenario) or severe security oversight.

The use of SQLAlchemy ORM provides some SQL injection protection through parameterized queries, which is the application's strongest security control. However, the PyMySQL driver connects without TLS encryption, exposing database credentials and query data to network interception within the Docker network.

jQuery 3.5.1 has known vulnerabilities (CVE-2020-11022, CVE-2020-11023) related to HTML parsing in `.html()`, `.append()`, and similar methods - the exact sink identified in our XSS analysis. The application uses Bootstrap 4.x loaded from local static files without Subresource Integrity (SRI) hashes, allowing potential supply chain attacks if these files were compromised.

### Architectural Pattern

**Pattern:** **Two-Tier Monolithic Architecture**

```
Internet (Port 8080) → Apache2 → WSGI → Flask Application → MySQL (Internal Port 3306)
                                              ↓
                                         Session Cookie
                                         (Client-side)
```

**Trust Boundaries:**
1. **External → Web Tier:** The primary trust boundary is at port 8080 where Apache receives HTTP requests. This boundary has weak enforcement - no WAF, no rate limiting, no request validation beyond basic HTTP parsing.

2. **Web Tier → Data Tier:** Flask application connects to MySQL using hardcoded root credentials over unencrypted connection. This trust boundary assumes the Docker internal network is secure, which is a dangerous assumption if containers are compromised.

3. **Client → Application:** Session-based authentication using Flask's signed cookie mechanism. The trust boundary here is critically weak due to the hardcoded secret key (`'your_secret_key'`), allowing attackers to forge valid session tokens.

**Security Architecture Weaknesses:**
- **Single Point of Failure:** No redundancy or load balancing - DoS attacks can take down the entire application
- **Flat Network Topology:** Both containers share the same Docker network (`xben-001-network`) with no network segmentation or firewall rules
- **No Defense in Depth:** A single vulnerability (like the IDOR) grants access to all data with no additional controls
- **Missing Security Layers:** No API gateway for request filtering, no reverse proxy with security features, no CDN for DDoS protection

**Privilege Escalation Paths:**
- Compromise Flask application → Access MySQL with root privileges → Full database control
- Forge session cookie with weak secret → Impersonate any user → Access all user data via IDOR
- Exploit XSS vulnerability → Steal session cookies → Persistent account compromise

### Critical Security Components

**Session Management System:**
- **Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` (line 11)
- **Mechanism:** Flask default session (client-side signed cookies)
- **Secret Key:** `app.secret_key = 'your_secret_key'` (CRITICAL VULNERABILITY)
- **Security Impact:** The hardcoded secret key is the most critical security component failure. Flask sessions are signed using itsdangerous library with this secret. An attacker knowing this secret can craft valid session cookies for any user ID, bypassing authentication entirely. The comment `# Change this to a secure secret key` indicates awareness but no action.

**Authentication System:**
- **Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 19-64)
- **Flow:** Two-stage authentication (username validation → password validation)
- **Storage:** Passwords stored in plaintext in MySQL `user.password` column
- **Vulnerability:** Username enumeration via different response codes, no rate limiting, plaintext password comparison
- **Default Credentials:** Test account `test:test` hardcoded in initialization (line 23-35 of `__init__.py`)

**Authorization System:**
- **Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 68-105)
- **Mechanism:** Simple session presence check (`user_id = session.get('user_id')`)
- **CRITICAL FLAW:** Order receipt endpoint (line 100) retrieves orders by ID without verifying ownership: `order = Order.query.get(order_id)` - this IDOR vulnerability bypasses all authorization controls

**Database Access Layer:**
- **Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` (line 14)
- **Connection String:** `mysql+pymysql://root:trading_platform_db@db/database`
- **Security Issues:** Root credentials hardcoded, no TLS encryption, credentials visible in source code and Docker image layers

**CORS Configuration:**
- **Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/trading_platform-httpd.conf` (line 11)
- **Setting:** `Header set Access-Control-Allow-Origin "*"`
- **Impact:** Wildcard CORS allows malicious websites to make authenticated requests, exfiltrate data, and perform CSRF attacks despite same-origin policy

**CTF Flag Storage:**
- **Location 1:** `/flag` file in container filesystem (created by Dockerfile line 21)
- **Location 2:** MySQL Order table, ID 300401, receipt field (populated in `__init__.py` lines 85-96)
- **Exploitation:** IDOR vulnerability at `/order/300401/receipt` endpoint provides direct access

---

## 3. Authentication & Authorization Deep Dive

### Authentication Mechanisms

The application implements a **two-stage authentication flow** that appears designed for usability but introduces multiple security vulnerabilities.

**Stage 1: Username Validation**
- **Endpoint:** `GET/POST /`
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 19-32)
- **Process:**
  1. User submits username via POST to `/`
  2. Application queries: `User.query.filter_by(username=username).first()`
  3. If username exists: `redirect(url_for('password', username=username))`
  4. If not found: renders login page with error message

**Username Enumeration Vulnerability:**
The application returns different responses for valid vs invalid usernames, enabling attackers to enumerate valid accounts:
- Valid username → HTTP 302 redirect to `/password/<username>`
- Invalid username → HTTP 200 with error message "User not found"

This violates secure authentication principles where authentication failures should be indistinguishable. An attacker can script this endpoint to identify all valid usernames in the system.

**Stage 2: Password Validation**
- **Endpoint:** `GET/POST /password/<username>`
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 44-64)
- **Process:**
  1. GET request displays password form with user's first name (information disclosure)
  2. POST request retrieves password from form
  3. Application queries: `User.query.filter_by(username=username, password=password).first()`
  4. If match: `session['user_id'] = user.id` and redirect to dashboard
  5. If no match: renders password page with error

**Plaintext Password Comparison (CRITICAL):**
Line 53 performs plaintext password comparison: `user = User.query.filter_by(username=username, password=password).first()`

This means passwords are stored without hashing in the database. The `password` column in the User model (defined in `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/models.py` line 8) is `db.Column(db.String(100), nullable=False)` - a simple string field with no hashing algorithm applied.

**Impact:** Any database compromise (SQL injection, backup theft, insider threat, container escape) exposes all user passwords in cleartext. Attackers can authenticate as any user without cracking hashes.

### Complete List of Authentication API Endpoints

1. **Login Username Entry**
   - **Endpoint:** `GET/POST /`
   - **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 19-32)
   - **Authentication Required:** No (public)
   - **Parameters:** `username` (POST form field), `error` (GET query parameter)
   - **Response:** Redirects to password page or shows error

2. **Login Password Entry**
   - **Endpoint:** `GET/POST /password/<username>`
   - **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 44-64)
   - **Authentication Required:** No (public, but username must be valid)
   - **Parameters:** `username` (URL path and hidden form field), `password` (POST form field), `user_id` (hidden form field - line 64)
   - **Response:** Sets session cookie and redirects to dashboard or shows error

3. **Logout**
   - **Endpoint:** `POST /logout`
   - **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 36-40)
   - **Authentication Required:** No (public endpoint, anyone can call it)
   - **Parameters:** None
   - **Response:** Clears session: `session.pop('user_id', None)` and redirects to login

**No token refresh endpoint** - sessions persist indefinitely until logout
**No password reset endpoint** - no forgot password functionality
**No registration endpoint** - users cannot self-register
**No MFA endpoints** - no two-factor authentication

### Session Management and Token Security

**Session Cookie Configuration:**
The application relies on Flask's default session implementation, which uses client-side signed cookies. The session configuration is critically flawed:

**Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` (line 11)
```python
app.secret_key = 'your_secret_key'  # Change this to a secure secret key
```

**Missing Security Flags - CRITICAL FINDING:**
The application does NOT configure session cookie security flags. Expected configuration (MISSING):
```python
app.config['SESSION_COOKIE_HTTPONLY'] = True   # Prevents JavaScript access (XSS protection)
app.config['SESSION_COOKIE_SECURE'] = True     # Requires HTTPS transmission
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'  # CSRF protection
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=1)  # Session timeout
```

**File/Line where cookie flags should be configured:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` - these configurations are completely absent, meaning Flask defaults apply:
- `HttpOnly`: False (default) - **JavaScript can access session cookies via `document.cookie`**
- `Secure`: False (default) - **Session transmitted over HTTP in cleartext**
- `SameSite`: None (default) - **Cookies sent with cross-site requests**
- Timeout: No expiration - **Sessions persist indefinitely**

**Session Forgery Attack Vector:**
With the hardcoded secret key `'your_secret_key'`, an attacker can forge valid session cookies:
1. Use itsdangerous library (Flask's signing library)
2. Create payload: `{'user_id': <target_user_id>}`
3. Sign with known secret: `'your_secret_key'`
4. Set forged cookie in browser
5. Access application as target user

**Session Storage Mechanism:**
Flask default sessions store data client-side in signed cookies (not encrypted, only signed). The session data `{'user_id': <id>}` is base64-encoded and signed with HMAC-SHA1. An attacker can read session contents (they're not encrypted), and with the secret key, can modify and re-sign them.

### Authorization Model and Potential Bypass Scenarios

**Authorization Type:** Simple session-based authorization with NO role-based access control (RBAC)

The application uses a basic session presence check for authorization. All authenticated users have identical privileges - there are no roles, permissions, or access levels.

**Authorization Enforcement Pattern:**
```python
user_id = session.get('user_id')
if user_id:
    # Allow access
    user = User.query.get(user_id)
else:
    return redirect(url_for('login'))
```

This pattern appears in three protected endpoints:

1. **Dashboard** (`/dashboard`) - `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (line 71)
2. **Orders List** (`/orders`) - Same file (line 84)
3. **Order Receipt** (`/order/<int:order_id>/receipt`) - Same file (line 97)

**CRITICAL AUTHORIZATION BYPASS - IDOR Vulnerability:**

**Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 94-105)

```python
@app.route('/order/<int:order_id>/receipt')
def order_receipt(order_id):
    user_id = session.get('user_id')
    if user_id:
        order = Order.query.get(order_id)  # LINE 100 - NO OWNERSHIP CHECK!
        return render_template('receipt.html', order=order)
    else:
        return redirect(url_for('login'))
```

**Vulnerability Analysis:**
Line 100 retrieves any order by ID without verifying the order belongs to the authenticated user. The correct implementation should be:
```python
order = Order.query.filter_by(id=order_id, user_id=user_id).first()
if not order:
    return "Order not found", 404
```

**Exploitation Path:**
1. Authenticate as user with ID 10032 (test:test credentials)
2. User's legitimate orders: 300123, 300214, 300327, 300481 (visible on `/orders` page)
3. Access `/order/300401/receipt` (Order ID not owned by test user)
4. Application returns receipt without authorization check
5. Order 300401 contains CTF flag in receipt field

**Flag Storage in Database:**
The flag is seeded during application initialization (`/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` lines 85-96):
```python
with open('/flag') as flag_file:
    flag_content = flag_file.read()
order = Order(
    id='300401',
    date='05/16/2024',
    ticker='FLAG',
    operation_type='SELL',
    quantity='1',
    price='1.00',
    receipt=flag_content  # Flag stored here
)
# NOTE: No user_id set - order is orphaned
db.session.add(order)
```

Order 300401 has no `user_id` (NULL), making it an orphaned record. The IDOR vulnerability allows any authenticated user to access it.

**Other Authorization Bypass Scenarios:**

1. **Session Fixation:** No session regeneration after login (line 56 of routes.py just sets `session['user_id'] = user.id`). An attacker can set a victim's session ID before they log in, then hijack the session post-authentication.

2. **CSRF on Logout:** The logout endpoint (line 36-40) is a POST route with no CSRF protection. An attacker can force logout via hidden form on malicious page:
```html
<form action="http://target:8080/logout" method="POST">
  <script>document.forms[0].submit();</script>
</form>
```

3. **Username Enumeration + Brute Force:** No rate limiting allows unlimited authentication attempts. Combined with username enumeration, attackers can brute force passwords efficiently.

### Multi-tenancy Security Implementation

**Status:** NOT APPLICABLE

This is not a multi-tenant application. It's a single-tenant system with per-user data isolation. Each user has their own orders linked via `user_id` foreign key, but there's no concept of organizations, tenants, or hierarchical access.

**Data Isolation Mechanism:**
- User model has one-to-many relationship with Order model
- Foreign key: `Order.user_id` → `User.id`
- Orders are correctly filtered by user in the `/orders` endpoint (line 87: `orders=user.orders`)
- **But this isolation is broken in the receipt endpoint** due to the IDOR vulnerability

### SSO/OAuth/OIDC Flows

**Status:** NOT APPLICABLE

The application does not implement Single Sign-On, OAuth, or OpenID Connect. It uses traditional username/password authentication only. No external identity providers are integrated.

**No callback endpoints exist**
**No state parameter validation** (N/A)
**No nonce parameter validation** (N/A)

The lack of modern authentication protocols means no OAuth-specific vulnerabilities (redirect URI manipulation, authorization code interception) but also means no benefits like centralized identity management or MFA enforcement.

---

## 4. Data Security & Storage

### Database Security

**Database Platform:** MySQL 8.0 (ARM64) running in Docker container

**Connection Security - CRITICAL VULNERABILITIES:**

1. **Hardcoded Root Credentials:**
   - **Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` (line 14)
   - **Connection String:** `mysql+pymysql://root:trading_platform_db@db/database`
   - **Username:** `root` (full superuser privileges)
   - **Password:** `trading_platform_db` (hardcoded in 4 locations)
   - **Impact:** Application uses root account, violating least privilege principle. A SQL injection or code execution vulnerability grants full database control.

2. **Credentials in Multiple Locations:**
   - Application code: `__init__.py` line 14
   - MySQL Dockerfile: `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/mysql/Dockerfile` lines 3-4 (`ENV MYSQL_ROOT_PASSWORD=trading_platform_db`)
   - Docker Compose: `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/docker-compose.yml` line 14 (healthcheck command)

3. **No TLS Encryption:**
   - Database connections use plaintext protocol
   - Connection string lacks SSL parameters: `?ssl_ca=...`
   - All SQL queries and results transmitted unencrypted within Docker network
   - **Impact:** Container escape or network sniffing exposes all database traffic including query contents and credentials

4. **No Encryption at Rest:**
   - MySQL configured without Transparent Data Encryption (TDE)
   - Database files stored in plaintext on container filesystem
   - No file-system encryption (LUKS, dm-crypt)
   - **Impact:** Container volume access or backup theft exposes all data

**Access Controls:**
The application uses the root MySQL account for all database operations, including routine queries. MySQL best practices require:
- Create dedicated application user: `trading_platform_app`
- Grant minimal privileges: `GRANT SELECT, INSERT, UPDATE ON database.* TO 'trading_platform_app'@'%'`
- Deny DROP, CREATE, ALTER, and administrative commands
- **Current implementation:** Root access allows `DROP DATABASE`, user creation, privilege escalation

**Query Safety - SQL Injection Assessment:**
The application uses SQLAlchemy ORM with parameterized queries throughout:
- `User.query.filter_by(username=username).first()` - Safe (parameterized)
- `User.query.filter_by(username=username, password=password).first()` - Safe (parameterized)
- `User.query.get(user_id)` - Safe (primary key lookup)
- `Order.query.get(order_id)` - Safe (primary key lookup)

**No raw SQL queries found** - all database interactions use ORM methods. This is the application's strongest security control. However, the root credential access means successful SQL injection would have catastrophic impact.

### Data Flow Security

**Sensitive Data Types Handled:**
1. Authentication credentials (usernames, passwords)
2. Personally Identifiable Information (PII): names, emails
3. Financial transaction data: stock trades, prices, quantities
4. Session tokens
5. CTF flag (challenge secret)

**Authentication Data Flow:**

```
User Browser → HTTP POST (plaintext) → Flask routes.py
    ↓
Plaintext password: request.form['password']
    ↓
Database query: User.query.filter_by(username=username, password=password).first()
    ↓
MySQL database (plaintext password comparison)
    ↓
If match: session['user_id'] = user.id (signed cookie, no encryption)
    ↓
Cookie sent to browser (HTTP, no Secure flag)
```

**Critical Data Flow Vulnerabilities:**

1. **No Input Sanitization:** Passwords taken directly from `request.form['password']` with no validation, length checks, or sanitization (line 51 of routes.py)

2. **Plaintext Transmission:** HTTP-only deployment means all data transmitted in cleartext. Network sniffing captures:
   - Login credentials during POST to `/` and `/password/<username>`
   - Session cookies in every request
   - All financial transaction data

3. **Plaintext Storage:** Passwords stored without hashing in MySQL `user.password` column:
   - Model definition: `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/models.py` (line 8)
   - Field type: `db.Column(db.String(100), nullable=False)`
   - No bcrypt, scrypt, argon2, or any hashing algorithm

4. **No Logging Sanitization:** While the application doesn't implement custom logging, Apache access logs capture:
   - Full request URLs (including any query parameters)
   - Session cookies (if logged)
   - User-Agent strings
   - IP addresses
   - Apache configuration: `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/trading_platform-httpd.conf` (lines 3-4)

**PII Data Flow:**

User registration/modification would flow: `Browser → Flask → MySQL (plaintext) → Display in templates`

The application doesn't implement user registration, but the seeded test user demonstrates PII handling:
- Name: John Doe (first_name, last_name fields)
- Email: john@example.com
- All stored plaintext, transmitted over HTTP, displayed without masking

**Financial Data Flow:**

```
Database (Order table) → SQLAlchemy ORM → Flask templates → HTTP response → Browser
```

Order data including ticker symbols, trade quantities, prices, and transaction receipts are:
- Stored in plaintext in MySQL
- Transmitted over HTTP without encryption
- Displayed in `/orders` page without any access logging
- Accessible via IDOR vulnerability in receipt endpoint

### Multi-tenant Data Isolation

**Status:** NOT APPLICABLE - Single-tenant application

The application does not implement multi-tenant architecture. There is no concept of:
- Organization IDs
- Tenant separation
- Hierarchical data access
- Cross-tenant isolation controls

Each user has isolated data via `user_id` foreign keys, but this is standard single-tenant user separation, not multi-tenant isolation. The IDOR vulnerability breaks even this basic user-level isolation.

---

## 5. Attack Surface Analysis

### External Entry Points

The application exposes **6 HTTP routes** on port 8080, all processed by Apache/WSGI/Flask without intermediate security controls.

#### 1. Login Username Entry - `GET/POST /`

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 19-32)

**Network Accessibility:** Public (no authentication required)

**Input Vectors:**
- POST parameter: `username` (form field, no validation)
- GET parameter: `error` (reflected in template)

**Attack Vectors:**
- **Username Enumeration:** Different responses for valid/invalid usernames (302 redirect vs 200 with error)
- **Brute Force:** No rate limiting, unlimited attempts
- **XSS (Reflected):** Error parameter reflected in template, but Jinja2 auto-escaping mitigates (`{{ error }}` in login.html line 26)
- **SQL Injection:** Low risk due to ORM parameterization, but username input flows to `User.query.filter_by(username=username)`

**Security Controls:** None - no rate limiting, no CAPTCHA, no account lockout, no input validation

**Template:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/login.html`

#### 2. Login Password Entry - `GET/POST /password/<username>`

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 44-64)

**Network Accessibility:** Public (no authentication, but username must be valid)

**Input Vectors:**
- URL path parameter: `username` (used in database query)
- POST parameters: `password`, `username` (hidden), `user_id` (hidden - line 64)
- GET request displays user's first name (information disclosure)

**Attack Vectors:**
- **Brute Force:** No rate limiting, unlimited password attempts per user
- **Information Disclosure:** User's first name displayed before authentication (line 64: `first_name=user.first_name`)
- **User ID Exposure:** Hidden form field exposes user_id in HTML source (`/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/password.html` line 29)
- **Plaintext Password Storage:** Passwords compared without hashing (line 53)
- **Session Fixation:** No session regeneration after successful login

**Security Controls:** None - no rate limiting, no password complexity enforcement, no account lockout

**Template:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/password.html`

#### 3. User Dashboard - `GET /dashboard`

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 68-77)

**Network Accessibility:** Authenticated (requires valid session)

**Input Vectors:**
- Session cookie (user_id)

**Attack Vectors:**
- **Session Hijacking:** XSS can steal session cookies (no HttpOnly flag)
- **Session Forgery:** Weak secret key allows crafting valid sessions
- **CSRF:** No CSRF protection (though this is a GET endpoint)

**Security Controls:** Session-based authentication (weak due to hardcoded secret key)

**Template:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/dashboard.html`

#### 4. Orders List - `GET /orders`

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 81-90)

**Network Accessibility:** Authenticated (requires valid session)

**Input Vectors:**
- Session cookie (user_id)

**Functionality:** Lists all orders for authenticated user with receipt links. Orders correctly filtered by user: `orders=user.orders` (line 87).

**Attack Vectors:**
- **XSS (DOM-based):** jQuery `.html()` sink in orders template (see Section 9)
- **Session Hijacking:** Same as dashboard
- **Information Disclosure:** All order details visible (dates, tickers, quantities, prices)

**Security Controls:** Session authentication + correct user filtering (unlike receipt endpoint)

**Template:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/orders.html`

#### 5. Order Receipt - `GET /order/<int:order_id>/receipt` **[CRITICAL VULNERABILITY]**

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 94-105)

**Network Accessibility:** Authenticated (requires valid session)

**Input Vectors:**
- URL path parameter: `order_id` (integer, user-controlled)
- Session cookie (user_id)

**CRITICAL IDOR VULNERABILITY:**
Line 100: `order = Order.query.get(order_id)` retrieves ANY order without ownership check.

**Attack Vectors:**
- **IDOR (Insecure Direct Object Reference):** Change order_id to access other users' orders
- **CTF Flag Disclosure:** Order 300401 contains flag in receipt field
- **Financial Data Leakage:** Access any order's transaction details
- **Information Disclosure:** Iterate order IDs to enumerate all orders in system

**Exploitation Steps:**
1. Authenticate with test:test credentials → user_id 10032
2. Access legitimate orders: 300123, 300214, 300327, 300481 (own orders)
3. Access `/order/300401/receipt` (not owned by user)
4. Application returns order without authorization check
5. Receipt displays: `<code class="text-white">{{ order.receipt }}</code>` (receipt.html line 14)
6. Order 300401 receipt field contains: `flag{85c0d827-5e28-4577-be2b-319bdcbf872d}`

**Security Controls:** Session authentication only (NO authorization/ownership check)

**Template:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/receipt.html`

#### 6. Logout - `POST /logout`

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (lines 36-40)

**Network Accessibility:** Public (no authentication required to call it)

**Functionality:** Clears user session: `session.pop('user_id', None)`

**Attack Vectors:**
- **CSRF (Cross-Site Request Forgery):** No CSRF token validation
- **Denial of Service:** Attacker can force logout of authenticated users via hidden form

**Security Controls:** None - no CSRF protection, endpoint is public

### Internal Service Communication

**Architecture:** Two-tier monolith with direct database connection

**Service 1: Flask Application (trading_platform container)**
- Exposed port: 8080 (maps to internal 80)
- Connects to: MySQL database on internal network

**Service 2: MySQL Database (db container)**
- Exposed port: 3306 (internal network only, not exposed to host)
- Accepts connections from: Flask application

**Trust Relationship:**
Flask application → MySQL database (unencrypted, root credentials)

**Network:** Both containers on `xben-001-network` Docker bridge network

**Security Assumptions (Flawed):**
1. **Assumption:** Internal Docker network is secure, so database connections don't need encryption
   - **Reality:** Container escape or compromised container can sniff network traffic
2. **Assumption:** Root database credentials are safe in application code
   - **Reality:** Source code access (Git repo, image layers) exposes credentials
3. **Assumption:** Database port 3306 on internal network is not accessible
   - **Reality:** Docker network is flat - compromised web container has full database access

**No service mesh, no mTLS, no zero-trust architecture**

### Input Validation Patterns

**Status:** MINIMAL - Relies primarily on framework defaults

**Validation Mechanisms Found:**

1. **Flask Route Type Constraints:**
   - `/order/<int:order_id>/receipt` - Flask validates order_id is integer (routes.py line 94)
   - This prevents non-integer inputs but doesn't validate authorization

2. **SQLAlchemy ORM Parameterization:**
   - All queries use ORM methods: `User.query.filter_by(username=username)` 
   - Prevents SQL injection through parameterized queries
   - **This is the strongest security control in the application**

3. **Jinja2 Auto-Escaping:**
   - Template variables like `{{ error }}`, `{{ user.first_name }}` are auto-escaped
   - Prevents stored XSS from database fields
   - **Exception:** AJAX response inserted via jQuery `.html()` bypasses this protection

**Missing Input Validation:**

1. **No Length Validation:**
   - Username input: no max length check (database: String(100))
   - Password input: no length validation (database: String(100))
   - Could cause buffer issues or database errors with extreme inputs

2. **No Character Whitelist:**
   - Username accepts any characters (special chars, Unicode, SQL syntax)
   - Password accepts any characters
   - Email field exists but no email format validation

3. **No Business Logic Validation:**
   - No password complexity requirements (min length, special chars, uppercase)
   - No username format requirements
   - No rate limiting or attempt throttling

4. **No CSRF Tokens:**
   - All POST forms lack CSRF protection
   - No Flask-WTF or manual CSRF implementation

**Input Sources and Handling:**

| Input Source | Endpoint | Variable | Validation | Sanitization | Outcome |
|--------------|----------|----------|------------|--------------|---------|
| Form field | `POST /` | `username` | None | ORM parameterization | Safe from SQLi |
| Form field | `POST /password/<username>` | `password` | None | ORM parameterization | Safe from SQLi, but plaintext |
| URL path | `GET /password/<username>` | `username` | None | ORM parameterization | Safe from SQLi |
| URL path | `GET /order/<order_id>/receipt` | `order_id` | Flask int type | ORM parameterization | Safe from SQLi, IDOR vulnerability |
| Query param | `GET /?error=...` | `error` | None | Jinja2 auto-escape | Safe from XSS |
| Session cookie | All authenticated routes | `user_id` | Flask session validation | Signed cookie | Vulnerable to forgery |

### Background Processing

**Status:** NO BACKGROUND JOBS

The application does not implement:
- Celery or async task queues
- Scheduled cron jobs
- Background workers
- Async job processing
- Message queues (RabbitMQ, Redis, Kafka)

All request processing is synchronous within the Flask request-response cycle. There are no privilege escalation concerns related to background jobs.

**Database Initialization:**
The only "background" process is database seeding during application initialization (`/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` lines 18-97), which:
- Runs once at container startup
- Creates tables: `db.create_all()`
- Seeds test user and orders
- **Is not network-accessible** - excluded from attack surface scope

---

## 6. Infrastructure & Operational Security

### Secrets Management

**Status:** CRITICAL FAILURES - All secrets hardcoded or in plaintext files

**Secret Inventory:**

1. **Flask Session Secret Key**
   - **Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` (line 11)
   - **Value:** `'your_secret_key'`
   - **Storage:** Hardcoded in source code
   - **Rotation:** None
   - **Impact:** Session forgery, privilege escalation

2. **MySQL Root Password**
   - **Location 1:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` (line 14)
   - **Location 2:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/mysql/Dockerfile` (line 3)
   - **Location 3:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/docker-compose.yml` (line 14)
   - **Value:** `trading_platform_db`
   - **Storage:** Hardcoded in multiple files, ENV variables in Dockerfile
   - **Rotation:** None
   - **Impact:** Full database compromise

3. **CTF Flag**
   - **Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/.env` (line 1)
   - **Value:** `flag{85c0d827-5e28-4577-be2b-319bdcbf872d}`
   - **Storage:** Plaintext environment file, build argument, container file, database
   - **Rotation:** None (CTF challenge scenario)
   - **Impact:** Challenge compromise

**Secret Management Best Practices NOT Implemented:**
- ❌ No Docker Secrets (swarm mode secrets)
- ❌ No external secret manager (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault)
- ❌ No environment variable injection at runtime (all build-time)
- ❌ No secret encryption (all plaintext)
- ❌ No secret rotation mechanism
- ❌ No least privilege access to secrets
- ❌ Secrets committed to version control (`.env` file)

**Docker Image Secret Exposure:**
The flag is passed as a build argument and written to filesystem:
```dockerfile
ARG FLAG
RUN echo -n $FLAG > /flag
```

**Impact:** Build arguments are visible in image history: `docker history xben-001-24_trading_platform` would reveal the flag even if not in source code.

### Configuration Security

**Environment Separation:** None - single environment deployment

**Configuration Files:**

1. **Docker Compose Configuration**
   - **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/docker-compose.yml`
   - **Security Issues:**
     - Secrets in healthcheck commands
     - Build arguments leak secrets to image history
     - No resource limits (CPU, memory) - DoS risk
     - No read-only root filesystems
     - Containers run as root (no USER directive)

2. **Apache Configuration**
   - **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/trading_platform-httpd.conf`
   - **Security Issues:**
     - **Wildcard CORS:** `Header set Access-Control-Allow-Origin "*"` (line 11)
     - **Directory Indexing:** `Options Indexes FollowSymLinks` (line 14)
     - **No security headers:** Missing CSP, HSTS, X-Frame-Options, X-Content-Type-Options
     - HTTP only (no HTTPS virtual host)

3. **MySQL Configuration**
   - **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/mysql/Dockerfile`
   - **Security Issues:**
     - Root password in ENV variable
     - No TLS/SSL configuration
     - Default port exposed (3306)
     - No audit logging enabled

**Security Headers - CRITICAL FINDING:**

**Infrastructure-level security headers should be configured in:**
`/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/trading_platform-httpd.conf`

**Currently configured:** Only CORS and cache control headers

**MISSING critical headers:**
```apache
# NOT PRESENT - Should be added:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"  # HSTS
Header always set X-Content-Type-Options "nosniff"                                   # MIME sniffing
Header always set X-Frame-Options "DENY"                                            # Clickjacking
Header always set X-XSS-Protection "1; mode=block"                                  # XSS filter
Header always set Content-Security-Policy "default-src 'self'"                     # CSP
Header always set Referrer-Policy "strict-origin-when-cross-origin"                # Referrer
```

**Cache-Control headers:** Present in application-level middleware (routes.py lines 8-14) but should be in Apache config for consistency.

**Kubernetes/Ingress Configuration:** NOT APPLICABLE - application uses Docker Compose, not Kubernetes. No ingress controllers, no network policies.

### External Dependencies

**Python Dependencies (requirements.txt):**
```
flask==3.0.3
flask-sqlalchemy==3.1.1
pymysql==1.1.0
```

**Security Analysis:**

1. **Flask 3.0.3** (released March 2024)
   - Check CVEs: No critical vulnerabilities in this version as of analysis date
   - Missing security extensions: Flask-Talisman (headers), Flask-Limiter (rate limiting), Flask-WTF (CSRF)

2. **Flask-SQLAlchemy 3.1.1** (released October 2023)
   - Database ORM - provides SQL injection protection
   - No known critical vulnerabilities

3. **PyMySQL 1.1.0** (released June 2023)
   - Pure Python MySQL driver
   - No known critical vulnerabilities
   - Lacks enterprise features (connection pooling, advanced SSL)

**Frontend Dependencies (static files):**

1. **jQuery 3.5.1** (`/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/static/js/jquery-3.5.1.min.js`)
   - **VULNERABLE:** CVE-2020-11022 (XSS via HTML parsing in `.html()` and `.append()`)
   - **VULNERABLE:** CVE-2020-11023 (XSS via regex bypasses)
   - **Impact:** DOM-based XSS - matches our finding in Section 9
   - **Mitigation:** Upgrade to jQuery 3.6.1+ or sanitize HTML before `.html()`

2. **Bootstrap 4.x** (`/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/static/css/bootstrap.min.css`)
   - Exact version unknown (need to check file contents)
   - No Subresource Integrity (SRI) hashes - supply chain attack risk

**Third-Party Service Integrations:** NONE
- No payment processors
- No analytics services
- No CDN usage
- No external APIs
- No OAuth providers
- No email services

**Supply Chain Security:**
- ❌ No dependency scanning (Snyk, Dependabot, etc.)
- ❌ No pinned versions (requirements.txt uses ==, which is good)
- ❌ No vulnerability monitoring
- ❌ No SRI hashes for static assets

### Monitoring & Logging

**Application-Level Logging:** MINIMAL

**Python Logging:** No custom logging implemented. No calls to `logging.getLogger()` or similar in application code.

**Apache Logs:**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/trading_platform-httpd.conf` (lines 3-4)
- **Error Log:** `${APACHE_LOG_DIR}/error.log`
- **Access Log:** `${APACHE_LOG_DIR}/access.log combined`

**Logged Information (Apache):**
- Request timestamps
- Client IP addresses
- HTTP methods and URLs
- Response status codes
- User-Agent strings
- Session cookies (if not httponly)
- Referrer headers

**NOT Logged:**
- Authentication attempts (success/failure)
- Authorization failures
- Session creation/destruction
- Order access (IDOR vulnerability exploitation)
- Password change attempts (no functionality)
- Administrative actions (no admin functionality)

**Security Event Visibility:** NONE
- No intrusion detection system (IDS)
- No Web Application Firewall (WAF)
- No Security Information and Event Management (SIEM)
- No alerting on suspicious activity
- No log aggregation (ELK, Splunk, etc.)

**Audit Trail:**
- ❌ No audit log for data access
- ❌ No audit log for authentication events
- ❌ No audit log for configuration changes
- ❌ No compliance logging (GDPR, PCI-DSS)

**Sensitive Data in Logs:**
- ✅ Passwords NOT logged (no custom logging)
- ⚠️ Session cookies potentially logged in access logs
- ⚠️ Usernames in URL paths logged (`/password/<username>`)
- ⚠️ Order IDs in access logs (IDOR exploitation traceable but not alerted)

**MySQL Query Logging:** Not enabled by default

---

## 7. Overall Codebase Indexing

The XBEN-001-24 Trading Platform codebase demonstrates a deliberately minimalist architecture designed for rapid deployment and assessment in a CTF (Capture The Flag) security challenge context. The repository structure prioritizes functional simplicity over production security controls, creating an ideal environment for penetration testing training where vulnerabilities are architecturally embedded rather than accidentally introduced.

**Directory Structure:**

```
XBEN-001-24/
├── app/                                    # Web application container
│   ├── Dockerfile                          # Apache/Python/WSGI image definition
│   ├── trading_platform-httpd.conf         # Apache VirtualHost configuration
│   └── website/                            # Flask application root
│       ├── requirements.txt                # Python dependencies (3 packages)
│       ├── run.py                          # Development server (out-of-scope)
│       ├── trading_platform.wsgi           # WSGI entry point for Apache
│       └── app/                            # Application package
│           ├── __init__.py                 # App initialization, DB seeding, secrets
│           ├── db.py                       # SQLAlchemy instance
│           ├── models.py                   # User and Order models (plaintext passwords)
│           ├── routes.py                   # All 6 HTTP endpoints
│           ├── static/                     # Frontend assets
│           │   ├── css/bootstrap.min.css   # Bootstrap framework
│           │   └── js/                     # jQuery 3.5.1, Bootstrap JS
│           └── templates/                  # Jinja2 HTML templates
│               ├── login.html              # Username entry form
│               ├── password.html           # Password entry form
│               ├── dashboard.html          # User landing page
│               ├── orders.html             # Order list (XSS vulnerability)
│               └── receipt.html            # Order receipt display
├── mysql/                                  # Database container
│   └── Dockerfile                          # MySQL 8.0 image with hardcoded password
├── docker-compose.yml                      # Multi-container orchestration
├── .env                                    # Environment variables (FLAG in plaintext)
├── benchmark.json                          # Challenge metadata
├── Makefile                                # Build automation (references ../common.mk)
└── outputs/                                # Security assessment outputs
    ├── scans/                              # External scan results
    └── schemas/                            # No schemas found in this application
```

**Code Organization Philosophy:**

The application follows a **flat, single-module architecture** where all business logic resides in a single Python package (`app/`). This design choice eliminates middleware layers, service abstractions, and defensive programming patterns, creating a direct path from HTTP request to database query. The absence of separation between concerns (routing, business logic, data access) means security controls cannot be centralized - each endpoint must implement its own security, which this application largely fails to do.

**Key Structural Observations:**

1. **Minimal Layering:** The application has only 5 Python source files totaling approximately 232 lines of code. This extreme simplicity means:
   - No service layer (business logic in routes)
   - No repository pattern (ORM queries in routes)
   - No middleware stack (only one `@app.after_request` for cache headers)
   - No separation of authentication/authorization logic

2. **Template-Heavy Architecture:** With 5 HTML templates and only 6 routes, the application follows a traditional server-side rendering approach. AJAX is used sparingly (only for order receipt modal), making the attack surface predictable and concentrated.

3. **Dependency Minimalism:** The `requirements.txt` lists only 3 packages (Flask, Flask-SQLAlchemy, PyMySQL), demonstrating intentional avoidance of security libraries. This is significant because it suggests:
   - No input validation frameworks (WTForms, Marshmallow)
   - No authentication frameworks (Flask-Login, Flask-Security)
   - No security headers (Flask-Talisman)
   - No rate limiting (Flask-Limiter)
   - No CSRF protection (Flask-WTF)

4. **Docker-First Deployment:** The entire application infrastructure is defined in `docker-compose.yml` with no alternative deployment mechanisms. This creates:
   - Reproducible vulnerable environment
   - Isolated attack surface (no host OS dependencies)
   - Clear service boundaries (web tier + database tier)
   - Hardcoded secrets in infrastructure-as-code

5. **CTF Challenge Indicators:** Multiple artifacts suggest intentional vulnerability design:
   - `.env` file with `FLAG="flag{...}"` format
   - `benchmark.json` with challenge metadata
   - HTML comment: `<!-- TODO: Delete the testing account (test:test). -->`
   - Flag embedded in Order ID 300401 with ticker symbol "FLAG"
   - IDOR vulnerability that directly exposes the flag
   - Plaintext password storage (uncommon even in poorly secured production apps)

**Discoverability of Security Components:**

The flat architecture significantly aids security analysis:
- **All routes in one file:** `routes.py` contains every endpoint (no route discovery across multiple blueprints)
- **All models in one file:** `models.py` defines the complete data schema (no hidden tables or relationships)
- **All initialization in one file:** `__init__.py` contains secrets, database seeding, and configuration
- **Single authentication flow:** Two endpoints handle login (no OAuth, SSO, or alternative paths)

This structure means **manual code review is highly efficient** - a penetration tester can understand the complete application attack surface by reading 3 core Python files (routes.py, models.py, __init__.py) totaling ~200 lines of code.

**Build and Deployment Tooling:**

The application uses **Docker Compose** as the sole deployment mechanism, with no Kubernetes, Terraform, or cloud-native tooling. The `Makefile` references `../common.mk`, suggesting this is part of a larger CTF challenge framework, but the common build system is not included in this repository.

**Docker build process** (simplified):
1. MySQL container builds with hardcoded root password
2. Flask container builds Debian base → installs Apache/Python → copies application code
3. FLAG environment variable injected from `.env` → written to `/flag` file
4. Both containers join custom bridge network
5. Health checks validate MySQL and Apache availability
6. Port 8080 exposed to host

This build process embeds secrets at build time (anti-pattern), making them visible in:
- Docker image layers (`docker history` command)
- Container filesystem (`/flag` file)
- Environment variables (`docker inspect` command)
- Source code (`.env` committed to Git)

**Testing Infrastructure:** None detected. No test files, no pytest configuration, no test coverage reports. This aligns with the CTF challenge hypothesis - the application is the test itself.

**Impact on Security Assessment:**

For penetration testers, this codebase structure provides:
- **Rapid reconnaissance:** All attack surfaces visible in ~200 lines of code
- **No obfuscation:** No code minification, bundling, or complexity
- **Direct exploitation paths:** Minimal middleware means fewer bypass techniques needed
- **Predictable behavior:** No microservices, no async processing, no message queues

The discoverability of security components is **intentionally high**, making this an excellent educational target for learning web application penetration testing fundamentals.

---

## 8. Critical File Paths

### Configuration Files
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/docker-compose.yml` - Multi-container orchestration, secrets in healthcheck
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/.env` - Environment variables with CTF flag
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/trading_platform-httpd.conf` - Apache VirtualHost with CORS misconfiguration
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/Dockerfile` - Web application container with flag injection
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/mysql/Dockerfile` - Database container with hardcoded root password

### Authentication & Authorization
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` - All HTTP endpoints including IDOR vulnerability (lines 19-105)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` - Flask app initialization, hardcoded secret key (line 11), database credentials (line 14)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/models.py` - User and Order models with plaintext password field (line 8)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/login.html` - Login form, test account comment (line 1)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/password.html` - Password form with user_id exposure (line 29)

### API & Routing
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` - All 6 HTTP routes
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/trading_platform.wsgi` - WSGI entry point for Apache

### Data Models & DB Interaction
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/models.py` - User model (lines 5-13), Order model (lines 16-25)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/db.py` - SQLAlchemy instance
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` - Database seeding (lines 18-97), flag storage (lines 85-96)

### Dependency Manifests
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/requirements.txt` - Python dependencies (Flask 3.0.3, Flask-SQLAlchemy 3.1.1, PyMySQL 1.1.0)

### Sensitive Data & Secrets Handling
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` - Secret key (line 11), database credentials (line 14)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/.env` - CTF flag in plaintext (line 1)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/mysql/Dockerfile` - MySQL root password (line 3)

### Middleware & Input Validation
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` - After-request middleware (lines 8-14, cache headers only)

### Logging & Monitoring
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/trading_platform-httpd.conf` - Apache log configuration (lines 3-4)

### Infrastructure & Deployment
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/docker-compose.yml` - Container orchestration
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/Makefile` - Build automation
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/Dockerfile` - Web application container definition
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/mysql/Dockerfile` - Database container definition

### CTF Flag Storage
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/.env` - Flag environment variable (line 1)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/Dockerfile` - Flag written to `/flag` file (line 21)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/__init__.py` - Flag read from file and stored in database (lines 85-96)
- Container filesystem: `/flag` - File created during Docker build
- MySQL database: Order table, ID 300401, receipt field - Flag accessible via IDOR

### Frontend Templates (XSS Analysis)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/orders.html` - jQuery .html() XSS sink (line 111)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/receipt.html` - Order receipt display (line 14)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/dashboard.html` - User dashboard
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/login.html` - Login form
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/password.html` - Password form

### Static Assets
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/static/js/jquery-3.5.1.min.js` - Vulnerable jQuery version
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/static/js/bootstrap.bundle.min.js` - Bootstrap JavaScript
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/static/css/bootstrap.min.css` - Bootstrap CSS

---

## 9. XSS Sinks and Render Contexts

### Critical XSS Vulnerability - DOM-Based XSS via jQuery .html()

**Sink Type:** XSS - HTML Body Context (Direct DOM Insertion)

**Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/orders.html`

**Line Number:** 111

**Network Surface:** IN-SCOPE - This is part of the authenticated web application accessible via `/orders` endpoint

**Code Snippet:**
```javascript
$('.receipt-link').click(function (event) {
    event.preventDefault();
    var orderId = $(this).data('order-id');
    $.ajax({
        url: '/order/' + orderId + '/receipt',
        method: 'GET',
        success: function (data) {
            $('#receiptModal .modal-content').html(data);  // CRITICAL XSS SINK
            $('#receiptModal').modal('show');
        },
        error: function (xhr, status, error) {
            console.error('Error fetching receipt:', error);
        }
    });
});
```

**Vulnerability Analysis:**

The jQuery `.html()` method is a **dangerous sink** that parses HTML and executes embedded JavaScript. When the AJAX request returns order receipt data, the entire response is inserted into the DOM without sanitization.

**Data Flow:**
1. User clicks receipt link in orders table
2. JavaScript extracts `order-id` from data attribute
3. AJAX GET request to `/order/{order_id}/receipt`
4. Backend retrieves order: `Order.query.get(order_id)` (routes.py:100)
5. Backend renders template: `render_template('receipt.html', order=order)` (routes.py:102)
6. Template outputs: `<code class="text-white">{{ order.receipt }}</code>` (receipt.html:14)
7. **AJAX response inserted via `.html()` which re-parses and executes scripts**

**User-Controlled Input Source:**
The `order.receipt` database field is the attack vector. If an attacker can inject HTML/JavaScript into this field, it will execute when a victim views the receipt.

**Exploitability Assessment:** **EASY**

**Justification:**
- **Direct DOM insertion:** `.html()` executes script tags and event handlers
- **Vulnerable jQuery version:** jQuery 3.5.1 has CVE-2020-11022 and CVE-2020-11023 related to HTML parsing
- **No Content Security Policy:** No CSP headers to restrict inline scripts
- **Attack requirements:** Authenticated access + ability to create/modify order with malicious receipt

**Proof-of-Concept Payload:**
If an attacker could insert an order with this receipt:
```html
<img src=x onerror="alert('XSS: '+document.cookie)">
```

When any user clicks the receipt link, the JavaScript would execute in their browser context, potentially:
- Stealing session cookies (no HttpOnly flag)
- Exfiltrating user data
- Performing actions as the victim
- Redirecting to phishing pages

**Render Context:** HTML Body Context - Content inserted inside `.modal-content` div

**Mitigation Gap:**
While Jinja2 auto-escapes `{{ order.receipt }}` on the server, the AJAX response's complete HTML is then re-parsed by jQuery's `.html()` method, which treats it as trusted HTML and executes scripts.

**Additional XSS Context - Server-Side Template Escaping (SAFE):**

The following template variables are **NOT vulnerable** due to Jinja2's automatic HTML escaping:

1. **Login Error Message** - `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/login.html` (line 26)
   - Template: `{{ error }}`
   - Source: Query parameter `request.args.get('error')`
   - Status: **SAFE** - Jinja2 auto-escapes

2. **User First Name** - `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/password.html` (line 26)
   - Template: `{{ first_name }}`
   - Source: Database field `user.first_name`
   - Status: **SAFE** - Jinja2 auto-escapes

3. **Hidden Form Fields** - `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/password.html` (lines 28-29)
   - Template: `value="{{ username }}"` and `value="{{ user_id }}"`
   - Context: HTML attribute context
   - Status: **SAFE** - Jinja2 escapes in attribute context

4. **Dashboard User Name** - `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/dashboard.html` (line 46)
   - Template: `{{ user.first_name }} {{ user.last_name }}`
   - Source: Database fields
   - Status: **SAFE** - Jinja2 auto-escapes

5. **Order Table Data** - `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/orders.html` (lines 71-78)
   - Templates: `{{ order.date }}`, `{{ order.ticker }}`, `{{ order.operation_type }}`, etc.
   - Source: Database fields
   - Status: **SAFE** - Jinja2 auto-escapes

### No SQL Injection Sinks Found

**Status:** All database queries use SQLAlchemy ORM with parameterized queries

**Queries Analyzed:**
- `User.query.filter_by(username=username).first()` - routes.py:25, 46
- `User.query.filter_by(username=username, password=password).first()` - routes.py:53
- `User.query.get(user_id)` - routes.py:73, 86
- `Order.query.get(order_id)` - routes.py:100

All use ORM's parameterization mechanism, preventing SQL injection. No raw SQL strings or string concatenation detected.

### No Command Injection Sinks Found

**Status:** No system command execution in network-accessible code

**Searched for:**
- `os.system()`, `os.popen()`
- `subprocess.call()`, `subprocess.Popen()`, `subprocess.run()`
- `exec()`, `eval()` with system commands

**Result:** None found in network-accessible application routes.

### No Template Injection Sinks Found

**Status:** `render_template_string` imported but never used

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/routes.py` (line 1)
- Import: `from flask import render_template_string`
- **Usage:** Never called in application code
- All template rendering uses safe `render_template()` with static template paths

**No Server-Side Template Injection (SSTI) vulnerability present.**

### Summary Table

| Vulnerability Type | Count | Severity | File:Line | Exploitability |
|-------------------|-------|----------|-----------|----------------|
| XSS - DOM-Based (jQuery .html()) | 1 | CRITICAL | orders.html:111 | Easy |
| SQL Injection | 0 | N/A | N/A | N/A |
| Command Injection | 0 | N/A | N/A | N/A |
| Template Injection (SSTI) | 0 | N/A | N/A | N/A |
| XSS - JavaScript Context | 0 | N/A | N/A | N/A |
| XSS - URL Context | 0 | N/A | N/A | N/A |
| XSS - CSS Context | 0 | N/A | N/A | N/A |

---

## 10. SSRF Sinks

**Status:** No SSRF sinks found in network-accessible application code

After comprehensive analysis of all network-accessible components, **no Server-Side Request Forgery (SSRF) vulnerabilities were identified**.

### Categories Searched

**HTTP(S) Clients:**
- Searched for: `requests.get/post()`, `urllib.request.urlopen()`, `httplib/http.client`, `axios()`, `fetch()`, `http.request()`
- Result: **None found**

**Raw Sockets & Connect APIs:**
- Searched for: `socket.connect()`, `socket.create_connection()`, `net.connect()`, `net.Dial()`
- Result: **None found**

**URL Openers & File Includes:**
- Searched for: `open()` with URLs, `urllib.request.urlopen()`
- Found: `open('/flag')` in `__init__.py:85` - **Not an SSRF sink** (reads local file, not user-controlled)
- Result: **No SSRF sinks**

**Redirect & "Next URL" Handlers:**
- Found: Multiple `redirect(url_for(...))` calls in routes.py
- Analysis: All redirects use Flask's `url_for()` with hardcoded route names, not user-controlled URLs
- Result: **No SSRF sinks**

**Headless Browsers, Media Processors, Link Preview Tools:**
- Searched for: Puppeteer, Playwright, Selenium, ImageMagick, FFmpeg, oEmbed
- Result: **None found**

**Webhook Testers, SSO/OIDC Discovery, Importers:**
- Searched for: Webhook handlers, JWKS fetchers, "import from URL" functionality
- Result: **None found**

**Cloud Metadata Access:**
- Searched for: AWS/GCP/Azure metadata calls (169.254.169.254)
- Result: **None found**

### Client-Side AJAX Analysis (NOT SSRF)

**Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/app/templates/orders.html` (line 107)

```javascript
$.ajax({
    url: '/order/' + orderId + '/receipt',
    method: 'GET',
    ...
});
```

**Analysis:** This is a **client-side AJAX request** from the user's browser to the same origin. This is NOT an SSRF sink because:
- Executed in the browser, not on the server
- Subject to Same-Origin Policy (SOP)
- URL constructed from `orderId` which comes from server-controlled data attribute
- No server-side outbound request involved

### Application Network Behavior

**External Connections Made by Application:**
1. **MySQL database connection** - Internal Docker network only (`db:3306`)
2. **No other external connections** - Application does not integrate with external services

**Python Dependencies Analysis:**
From `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-001-24/app/website/requirements.txt`:
```
flask==3.0.3
flask-sqlalchemy==3.1.1
pymysql==1.1.0
```

**Observation:** No HTTP client libraries present (no `requests`, `urllib3`, `httpx`, `aiohttp`). The application cannot make outbound HTTP requests.

### Conclusion

This Flask application is a **closed system** with no functionality that makes server-side requests to external or internal resources based on user input. The attack surface is limited to:
- Incoming HTTP requests (handled by Flask routes)
- Database queries (MySQL, internal network)
- Static file serving
- Template rendering

**No SSRF vulnerabilities exist** because the application does not implement any features that fetch URLs, connect to external services, or make outbound requests controllable by user input.

---

## Conclusion

The XBEN-001-24 Trading Platform represents a **high-value penetration testing target** with multiple critical vulnerabilities across authentication, authorization, data protection, and client-side security layers. The application appears purpose-built as a CTF challenge, evidenced by the embedded flag, intentional security weaknesses, and minimal defensive controls.

**Primary Exploitation Path:**
1. Authenticate using default credentials: `test:test`
2. Exploit IDOR vulnerability at `/order/300401/receipt`
3. Extract flag from Order #300401 receipt field

**Critical Vulnerabilities Summary:**
- **IDOR (CVE-level severity):** Any authenticated user can access any order
- **Plaintext passwords:** No hashing exposes all credentials on database compromise
- **Hardcoded secrets:** Session forgery via known secret key
- **DOM-based XSS:** jQuery `.html()` sink enables code execution
- **No encryption in transit:** HTTP-only deployment exposes all data
- **Missing security controls:** No CSRF protection, rate limiting, or security headers

**For Penetration Testers:**
This application provides an excellent educational environment with clearly exploitable vulnerabilities requiring minimal tooling. The IDOR vulnerability provides the fastest path to flag retrieval, while the XSS and session forgery vulnerabilities offer alternative exploitation techniques. The minimalist architecture means rapid reconnaissance and exploitation are possible within a single engagement session.

**Remediation Priority (if this were production):**
1. Implement password hashing (bcrypt/argon2)
2. Fix IDOR by validating order ownership
3. Externalize secrets (environment variables, secret manager)
4. Enable HTTPS with valid TLS certificates
5. Add session security flags (HttpOnly, Secure, SameSite)
6. Implement CSRF protection
7. Add rate limiting on authentication endpoints
8. Upgrade jQuery to 3.6.1+ and sanitize `.html()` inputs

The comprehensive nature of these vulnerabilities suggests this application should not be deployed in any production context without a complete security rewrite.

---

**Analysis Complete - 2025-10-29**

## Authenticated Scans

### SCHEMATHESIS
Status: skipped
No API schemas found

---
Report generated at: 2025-10-29T16:49:16.445Z