Skip to content

About

TaintedPort - Portuguese Wine Store · Security Test Application

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

TaintedPort - Portuguese Wine Store (Security Test App)

A deliberately vulnerable Portuguese wine e-commerce application built with Next.js and PHP, designed for DAST and security testing. Packaged as a single Docker container for easy deployment.

WARNING: This is NOT a real store. It is an intentionally vulnerable application for security testing purposes only. Wine names, prices, and descriptions are fictional.

Hostnames

Service Hostname Description
Frontend taintedport.com Next.js web application
API api.taintedport.com PHP REST API

Both are served from a single container via nginx virtual hosts.

Quick Start (Docker - Local)

The fastest way to run TaintedPort locally is to pull the prebuilt image:

docker run -p 8080:80 nunoloureiro/taintedport:latest

Then open http://localhost:8080. Locally, the API is reachable at http://localhost:8080/api/ (path-based routing). The database resets automatically every time the container starts, giving you a clean environment.

Build from source

./build.sh                  # lint, build, push
./build.sh --no-push        # build only

docker-compose.yml runs the same flow with API_URL=/api for local hostnames.

For Docker Compose, docker-compose.yml already wires the additional context and uses API_URL=/api so the frontend talks to the API via path-based routing:

docker compose up -d

See DeployInstructions.txt for the full publish + deploy flow.

Demo Accounts

User Email Password Role
Joe Silva joe@example.com password123 User
Jane Doe jane@example.com password123 User
Admin admin@example.com password123 Admin
Sam Support support@example.com password123 Support

Joe and Jane have pre-seeded orders, wishlist items and support tickets. The admin account has full access to /admin (overview, orders, wines & stock, discount/referral codes, support inbox, team & roles). The support account can only access order management and the support inbox.

Local Development (without Docker)

1. Set up the Database

cd backend
php setup_db.php

2. Start the Backend

cd backend
php -S localhost:8000 router.php

3. Start the Frontend

cd frontend
npm install
npm run dev

App at http://localhost:3000, API at http://localhost:8000/api/.

AWS Deployment (EC2)

Run TaintedPort on a cheap EC2 instance (~$5-10/month with a t2.nano or t3.micro).

DNS Setup

Point both domains to your EC2 instance's public IP:

Record Type Value
taintedport.com A <EC2_PUBLIC_IP>
api.taintedport.com A <EC2_PUBLIC_IP>

Deploy to EC2

  1. Launch an EC2 instance (Amazon Linux 2023 or Ubuntu, t2.nano is fine)
  2. Open ports 80 and 443 in the security group
  3. SSH in and run:
# Copy the project to the instance (or git clone)
scp -r . ec2-user@YOUR_IP:~/taintedport/

# SSH in
ssh ec2-user@YOUR_IP

# Run the setup script
cd ~/taintedport
./aws/setup-ec2.sh

That's it. The script installs Docker, builds the image, starts the container on port 80, and sets up a cron job to restart it every Monday at 00:00 UTC (which resets the database to a clean state).

Useful commands on the instance

docker logs taintedport          # View logs
docker restart taintedport       # Manual reset (fresh DB)
docker stop taintedport          # Stop
docker start taintedport         # Start

Weekly Reset

A cron job runs docker restart taintedport every Monday at 00:00 UTC. Since the container entrypoint always resets the SQLite database on start, this gives a fresh environment each week.

Distribute the Container

Push to Docker Hub (for sharing)

./build.sh

Others can then run:

docker run -p 8080:80 nunoloureiro/taintedport:latest

Tech Stack

  • Frontend: Next.js 14 (standalone) + Tailwind CSS 3
  • Backend: PHP 8 (PHP-FPM) + SQLite3
  • Proxy: nginx (virtual hosts: taintedport.com + api.taintedport.com)
  • Process Manager: supervisord (nginx + PHP-FPM + Node.js)
  • Authentication: JWT (HS256) + TOTP 2FA
  • Container: Single Docker image (~200MB)

API Endpoints

Authentication

Method Endpoint Description
POST /api/auth/register Register a new user
POST /api/auth/login Login and get JWT token
GET /api/auth/me Get current user (requires auth)
PUT /api/auth/profile Update name (requires auth)
PUT /api/auth/email Change email (requires auth + password)
PUT /api/auth/password Change password (requires auth + current password)
POST /api/auth/2fa/setup Generate TOTP secret + QR URI (requires auth)
POST /api/auth/2fa/enable Enable 2FA with secret + code (requires auth)
POST /api/auth/2fa/disable Disable 2FA (requires auth + password)

Wines

Method Endpoint Description
GET /api/wines List wines (with search, filter, sort)
GET /api/wines/:id Get wine details
GET /api/wines/regions List available regions
GET /api/wines/types List available types

Cart (requires auth)

Method Endpoint Description
GET /api/cart Get cart items
POST /api/cart/add Add item to cart
PUT /api/cart/update Update item quantity
DELETE /api/cart/remove/:wine_id Remove item from cart

Orders (requires auth)

Method Endpoint Description
POST /api/orders Place an order
GET /api/orders List user's orders
GET /api/orders/:id Get order details

Admin (requires admin role)

Method Endpoint Description
GET /api/admin/orders List all orders
GET /api/admin/orders/:id Get order details (admin view)
PUT /api/admin/orders/:id/status Update order status

Features

  • JWT-based authentication with 7-day token expiry
  • TOTP-based two-factor authentication (2FA) with QR code scanning
  • Editable user profile (name, email, password)
  • Responsive dark-themed UI inspired by Snyk Labs
  • Wine catalog with search, filter by region/type, sort, and price range
  • Shopping cart with quantity management
  • Checkout with shipping address and payment on delivery
  • User account with order history and security settings
  • 24 seeded Portuguese wines from 7+ regions
  • Admin dashboard for order management (status updates)
  • About page with disclaimers
  • Global footer on every page
  • Auto-reset database on container start

Contributing — vuln-leak guard

This repo holds the vulnerable app, never the answer key. The known-vuln catalog, CWE/severity mappings and exploit notes live only in the private companion repo and are injected at build time. A guard enforces this:

python3 tests/check_no_vuln_leak.py     # run manually anytime (also a pytest test)

It runs automatically on every git push via a pre-push hook. After cloning, enable the hook once:

git config core.hooksPath .githooks

If the guard flags a genuine, intentional overlap with real app code, accept it with python3 tests/check_no_vuln_leak.py --update-baseline (stores one-way hashes only — never plaintext).

Project Structure

Dockerfile              # Multi-stage build (Node + PHP + nginx)
docker-compose.yml      # Local container orchestration
docker/
  nginx.conf            # Reverse proxy config
  supervisord.conf      # Process manager config
  entrypoint.sh         # DB reset + service startup
aws/
  setup-ec2.sh          # EC2 setup script (Docker + cron)

backend/
  api/
    config/             # Database, JWT, TOTP configuration
    controllers/        # Request handlers
    middleware/          # Auth middleware
    models/             # Data models
    index.php           # API entry point
  router.php            # PHP dev server router
  setup_db.php          # Database setup & seed script

frontend/
  app/                  # Next.js pages (App Router)
  components/           # Logo, Navbar, Footer, WineBottle, etc.
  context/              # Auth and Cart context providers
  lib/                  # API client

About

TaintedPort - Portuguese Wine Store · Security Test Application

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages