Skip to content

Penetration Testing Research Report

Status: Research Document
Created: February 2026
Scope: Forma 3D Connect Staging Environment
Classification: Internal — Do Not Distribute

Table of Contents

  1. Executive Summary
  2. Scope and Target Inventory
  3. Methodology — Independent Pentest Approach
  4. Phase 1 — Reconnaissance and OSINT
  5. Phase 2 — DNS and Infrastructure Assessment
  6. Phase 3 — Web Application Testing
  7. Phase 4 — API Security Testing
  8. Phase 5 — Server-Side Assessment (With SSH Access)
  9. Phase 6 — Database Security Assessment
  10. Phase 7 — Container and Supply Chain Security
  11. Phase 8 — Authentication and Session Testing
  12. Phase 9 — Business Logic Testing
  13. Toolchain Reference
  14. Report Deliverables
  15. NIS2 Compliance Evaluation
  16. Recommended Pentest Schedule
  17. Cost Estimates and Vendor Options

1. Executive Summary

This document researches how to independently conduct a penetration test against the Forma 3D Connect staging environment. It covers the full lifecycle: reconnaissance, active scanning, exploitation attempts, server-side review, and compliance mapping against NIS2 (the EU Network and Information Security Directive 2).

Why Penetration Test Staging?

  • Safe testing ground: Staging mirrors production architecture without risking real customer data
  • NIS2 readiness: Directive requires regular security assessments for essential and important entities
  • Proactive posture: Identify vulnerabilities before attackers do
  • Compliance evidence: Documented pentest results serve as audit artifacts

Staging Environment Overview

Component Target
Web Application https://staging-connect.forma3d.be
REST API https://staging-connect-api.forma3d.be
API Documentation https://staging-connect-api.forma3d.be/api/docs
pgAdmin https://staging-connect-db.forma3d.be
Droplet IP 167.172.45.47
Reverse Proxy Traefik v3 (TLS termination, Let's Encrypt)
Application NestJS (API) + React 19 (Web)
Database DigitalOcean Managed PostgreSQL (port 25060, SSL required)
DNS Provider forma3d.be domain
CI/CD Azure DevOps

2. Scope and Target Inventory

2.1 In-Scope Targets

Target Type Priority
staging-connect.forma3d.be Web Application (React SPA) High
staging-connect-api.forma3d.be REST API (NestJS) Critical
staging-connect-db.forma3d.be pgAdmin Web Interface High
167.172.45.47 DigitalOcean Droplet (Ubuntu) Critical
forma3d.be DNS Zone Medium
*.forma3d.be Subdomain Enumeration Medium
Docker containers on droplet Container Security High
Webhook endpoints Integration Security High

2.2 Out-of-Scope

Target Reason
Shopify infrastructure Third-party, separate bug bounty
SimplyPrint infrastructure Third-party
SendCloud infrastructure Third-party
DigitalOcean control plane Third-party, separate bug bounty
Production environment Risk of real data exposure

2.3 Rules of Engagement

Before any pentest, define and document:

## Rules of Engagement

- Testing window: [Agreed dates and times]
- Emergency contact: [Phone/email for immediate escalation]
- Allowed actions: Scanning, enumeration, exploitation attempts on staging
- Forbidden actions: DoS attacks, data exfiltration of real PII, lateral movement to production
- Data handling: All findings stored encrypted, destroyed after report delivery
- Notification: Team notified before testing begins
- Rollback plan: Staging can be redeployed from pipeline if disrupted

3. Methodology — Independent Pentest Approach

3.1 Testing Standard

Follow the OWASP Testing Guide v4.2 and PTES (Penetration Testing Execution Standard) as the primary methodology frameworks. Map findings to OWASP Top 10 (2021) categories.

3.2 Testing Phases

┌─────────────────────────────────────────────────────────────────────┐
│                    PENETRATION TEST LIFECYCLE                        │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Phase 1         Phase 2         Phase 3         Phase 4            │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐        │
│  │ Recon &  │──▶│ DNS &    │──▶│ Web App  │──▶│ API      │        │
│  │ OSINT    │   │ Infra    │   │ Testing  │   │ Testing  │        │
│  └──────────┘   └──────────┘   └──────────┘   └──────────┘        │
│                                                                     │
│  Phase 5         Phase 6         Phase 7         Phase 8            │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐        │
│  │ Server   │──▶│ Database │──▶│ Container│──▶│ Auth &   │        │
│  │ (SSH)    │   │ Security │   │ & Supply │   │ Session  │        │
│  └──────────┘   └──────────┘   │ Chain    │   └──────────┘        │
│                                 └──────────┘                        │
│  Phase 9                                                            │
│  ┌──────────┐   ┌──────────┐                                       │
│  │ Business │──▶│ Report & │                                       │
│  │ Logic    │   │ NIS2 Map │                                       │
│  └──────────┘   └──────────┘                                       │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

3.3 Two Perspectives

Perspective Description Access Level
Black Box (External) No credentials, attacker perspective Public endpoints only
Grey Box (Authenticated + SSH) With application credentials and SSH access Full server access

Both perspectives should be tested in sequence — black box first, then grey box.


4. Phase 1 — Reconnaissance and OSINT

4.1 Passive Reconnaissance

Gather intelligence without directly touching the target.

Tools

Tool Purpose Command
theHarvester Email, subdomain, host discovery theHarvester -d forma3d.be -b all -l 500
Shodan Exposed services, banners, CVEs Search: hostname:forma3d.be
Censys Certificate transparency, services Search: forma3d.be
crt.sh Certificate Transparency logs curl -s "https://crt.sh/?q=%25.forma3d.be&output=json" \| jq
Google Dorks Indexed sensitive files site:forma3d.be filetype:env OR filetype:sql OR filetype:log
Wayback Machine Historical endpoint discovery waybackurls forma3d.be
GitHub/GitLab Search Leaked credentials, config Search: "forma3d" password OR secret OR api_key
SecurityTrails DNS history, subdomains API or web interface

What to Look For

  • Leaked API keys, secrets, or .env files in public repos
  • Exposed admin panels or debug endpoints
  • Certificate details revealing internal hostnames
  • Historical endpoints that may still be active
  • Email addresses for social engineering vectors
  • Technology fingerprints (headers, JavaScript files)

4.2 Active Reconnaissance

Direct interaction with the target.

# Subdomain enumeration
subfinder -d forma3d.be -all -o subdomains.txt
amass enum -passive -d forma3d.be -o amass-subdomains.txt

# Combine and deduplicate
cat subdomains.txt amass-subdomains.txt | sort -u > all-subdomains.txt

# Resolve live subdomains
httpx -l all-subdomains.txt -o live-hosts.txt -status-code -title -tech-detect

# Screenshot all live hosts
gowitness file -f live-hosts.txt -P screenshots/

5. Phase 2 — DNS and Infrastructure Assessment

5.1 DNS Security Checks

Check Tool Command
Zone Transfer dig dig axfr forma3d.be @ns1.provider.com
DNSSEC Validation dig dig forma3d.be +dnssec
SPF Record dig dig forma3d.be TXT \| grep spf
DMARC Record dig dig _dmarc.forma3d.be TXT
DKIM Record dig dig default._domainkey.forma3d.be TXT
MX Records dig dig forma3d.be MX
CAA Records dig dig forma3d.be CAA
NS Records dig dig forma3d.be NS
Subdomain Takeover subjack subjack -w all-subdomains.txt -t 100 -timeout 30 -o takeover.txt

5.2 DNS Findings Checklist

## DNS Security Assessment

- [ ] Zone transfer blocked (AXFR denied)
- [ ] DNSSEC enabled and valid
- [ ] SPF record present and restrictive (ends with -all)
- [ ] DMARC record present with p=reject or p=quarantine
- [ ] DKIM configured for mail-sending domains
- [ ] CAA record restricts certificate issuance to authorized CAs
- [ ] No dangling CNAME records (subdomain takeover risk)
- [ ] No wildcard DNS records unless intentional
- [ ] NS records point to reputable provider
- [ ] No TXT records leaking sensitive information

5.3 Infrastructure Scanning

Port Scanning

# Full TCP scan of the droplet
nmap -sS -sV -sC -p- -oA nmap-full 167.172.45.47

# UDP top ports
nmap -sU --top-ports 100 -oA nmap-udp 167.172.45.47

# Aggressive scan with OS detection
nmap -A -T4 -oA nmap-aggressive 167.172.45.47

# Script scan for vulnerabilities
nmap --script vuln -oA nmap-vuln 167.172.45.47

Expected Open Ports (Staging)

Port Service Expected Action if Unexpected
22/tcp SSH Yes (UFW allowed) Verify key-only auth
80/tcp HTTP Yes (Let's Encrypt challenge + redirect) Verify redirect to 443
443/tcp HTTPS Yes (Traefik) Test TLS configuration
25060/tcp PostgreSQL No (managed, external) Should NOT be open on droplet
Other No Investigate and close

5.4 TLS/SSL Assessment

# Comprehensive TLS test
testssl.sh --html staging-connect-api.forma3d.be

# Alternative: sslyze
sslyze staging-connect-api.forma3d.be staging-connect.forma3d.be staging-connect-db.forma3d.be

# Quick SSL Labs grade (manual)
# Visit: https://www.ssllabs.com/ssltest/analyze.html?d=staging-connect-api.forma3d.be

TLS Checklist

## TLS Security Assessment

- [ ] TLS 1.2+ only (TLS 1.0/1.1 disabled)
- [ ] Strong cipher suites (no RC4, DES, 3DES, NULL)
- [ ] Perfect Forward Secrecy (PFS) enabled
- [ ] HSTS header present with long max-age
- [ ] HSTS includeSubDomains set
- [ ] HSTS preload set (or planned)
- [ ] Certificate valid and not near expiry
- [ ] Certificate chain complete
- [ ] No certificate transparency issues
- [ ] OCSP stapling enabled
- [ ] HTTP redirects to HTTPS (no mixed content)
- [ ] SSL Labs grade A or A+

6. Phase 3 — Web Application Testing

6.1 Automated Scanning

OWASP ZAP (Primary Scanner)

# Start ZAP in daemon mode
zap.sh -daemon -port 8080 -config api.key=your-api-key

# Spider the application
zap-cli spider https://staging-connect.forma3d.be

# Active scan
zap-cli active-scan https://staging-connect.forma3d.be

# Generate HTML report
zap-cli report -o zap-report.html -f html

Nuclei (Template-Based Scanner)

# Run all templates against web targets
nuclei -u https://staging-connect.forma3d.be -o nuclei-web.txt
nuclei -u https://staging-connect-api.forma3d.be -o nuclei-api.txt
nuclei -u https://staging-connect-db.forma3d.be -o nuclei-pgadmin.txt

# Run with specific severity
nuclei -u https://staging-connect.forma3d.be -severity critical,high -o nuclei-critical.txt

# Technology-specific templates
nuclei -u https://staging-connect-api.forma3d.be -tags nodejs,express,nestjs -o nuclei-nestjs.txt

Nikto (Web Server Scanner)

# Scan web and API endpoints
nikto -h https://staging-connect.forma3d.be -o nikto-web.html -Format html
nikto -h https://staging-connect-api.forma3d.be -o nikto-api.html -Format html
nikto -h https://staging-connect-db.forma3d.be -o nikto-pgadmin.html -Format html

6.2 Manual Web Application Testing (OWASP Top 10)

A01:2021 — Broken Access Control

Test How Tool
Forced browsing Try accessing admin pages without auth Browser / Burp
IDOR Modify IDs in URLs/requests to access other users' data Burp Repeater
Privilege escalation Test if regular user can access admin endpoints Burp / curl
CORS misconfiguration Send requests with arbitrary Origin header curl / Burp
Directory traversal Attempt ../ in file paths Burp Intruder
# Test CORS
curl -H "Origin: https://evil.com" -I https://staging-connect-api.forma3d.be/health
# Check: Access-Control-Allow-Origin should NOT be * or reflect arbitrary origins

# Test forced browsing
curl https://staging-connect-api.forma3d.be/api/v1/admin/users
# Should return 401/403 without valid session

A02:2021 — Cryptographic Failures

Test How
Sensitive data over HTTP Verify all resources served over HTTPS
Weak hashing Check password storage algorithm (bcrypt expected)
Sensitive data in URL Check for tokens/passwords in query strings
Insecure cookies Verify Secure, HttpOnly, SameSite attributes

A03:2021 — Injection

Test How Tool
SQL injection Inject payloads in all input fields sqlmap / Burp
NoSQL injection Test JSON body parameters Burp
Command injection Test parameters that might interact with OS Manual
XSS (Reflected) Inject script tags in URL params Burp / dalfox
XSS (Stored) Inject payloads in stored fields Burp
Template injection Test for SSTI in rendered content tplmap
# XSS scanning with dalfox
dalfox url "https://staging-connect.forma3d.be/search?q=test" -o dalfox-results.txt

# SQL injection testing (should fail — Prisma ORM prevents this)
sqlmap -u "https://staging-connect-api.forma3d.be/api/v1/orders?id=1" --batch --risk=3 --level=5

A04:2021 — Insecure Design

Test How
Rate limiting bypass Test if rate limits can be bypassed via headers (X-Forwarded-For)
Business logic flaws Attempt to skip steps in order workflows
Missing anti-automation Check for CAPTCHA on auth endpoints

A05:2021 — Security Misconfiguration

Test How Tool
Security headers Check all response headers securityheaders.com / curl
Debug endpoints Check for /debug, /metrics, /swagger exposed ffuf
Default credentials Test common admin/admin combinations Manual
Stack traces Trigger errors, check for verbose messages Manual
Directory listing Check if directories are browsable Browser
# Security headers check
curl -sI https://staging-connect-api.forma3d.be/health | grep -iE \
  "strict-transport|content-security|x-frame|x-content-type|referrer-policy|permissions-policy"

# Directory/endpoint fuzzing
ffuf -w /usr/share/seclists/Discovery/Web-Content/common.txt \
  -u https://staging-connect-api.forma3d.be/FUZZ \
  -mc 200,301,302,403 \
  -o ffuf-api-dirs.json

# Check Swagger/API docs accessibility
curl -s https://staging-connect-api.forma3d.be/api/docs | head -20

A06:2021 — Vulnerable and Outdated Components

Test How Tool
JavaScript libraries Identify client-side libraries and versions retire.js / Wappalyzer
Server framework Fingerprint NestJS version Response headers
Known CVEs Cross-reference versions with CVE databases Nuclei / Trivy

A07:2021 — Identification and Authentication Failures

Test How
Brute force Attempt multiple login failures, check lockout
Session fixation Check if session ID changes after login
Session timeout Verify sessions expire appropriately
Password policy Test weak passwords during registration
Credential stuffing Test common credential pairs

A08:2021 — Software and Data Integrity Failures

Test How
CI/CD pipeline security Review Azure DevOps pipeline configuration
Image signing Verify cosign signatures on container images
Dependency integrity Verify lockfile integrity
Webhook integrity Test HMAC verification bypass

A09:2021 — Security Logging and Monitoring Failures

Test How
Failed login logging Verify failed attempts are logged
Sensitive data in logs Check logs for PII or credentials
Log injection Attempt to inject log entries
Alerting Verify Sentry captures security events

A10:2021 — Server-Side Request Forgery (SSRF)

Test How
URL parameter manipulation Test parameters accepting URLs for SSRF
Webhook URL manipulation Attempt to register internal URLs as webhooks
DNS rebinding Test if internal IPs can be reached via DNS tricks

6.3 pgAdmin-Specific Testing

The exposed pgAdmin instance at staging-connect-db.forma3d.be is a high-value target.

## pgAdmin Security Checklist

- [ ] Default credentials changed
- [ ] Brute force protection enabled
- [ ] Access restricted to authorized IPs (or behind VPN)
- [ ] HTTPS enforced
- [ ] Session timeout configured
- [ ] pgAdmin version is current (check for known CVEs)
- [ ] Server credentials not exposed in UI
- [ ] No public access to query tool

7. Phase 4 — API Security Testing

7.1 API Discovery

# Fetch OpenAPI/Swagger spec
curl -s https://staging-connect-api.forma3d.be/api/docs-json | jq > swagger.json

# Parse all endpoints
cat swagger.json | jq -r '.paths | keys[]' > api-endpoints.txt

# Generate Postman collection from Swagger
# Import swagger.json into Postman or use openapi-to-postman

7.2 API-Specific Testing Tools

Tool Purpose Usage
Burp Suite Professional Comprehensive API proxy and scanner Primary testing proxy
Postman API request crafting and collections Organized endpoint testing
Dredd API contract testing (Swagger compliance) dredd swagger.json https://staging-connect-api.forma3d.be
Schemathesis Property-based API testing schemathesis run https://staging-connect-api.forma3d.be/api/docs-json
RESTler Stateful REST API fuzzing (Microsoft) Automated sequence-aware fuzzing

7.3 API Security Test Matrix

Category Test Method
Authentication Missing auth on protected endpoints Call each endpoint without API key/session
Authentication Invalid API key handling Send malformed/expired API keys
Authorization Horizontal privilege escalation Access other tenants' resources
Authorization Vertical privilege escalation Access admin endpoints as regular user
Input Validation Oversized payloads Send requests exceeding expected size
Input Validation Unexpected data types Send strings where numbers expected
Input Validation Special characters Unicode, null bytes, control characters
Input Validation Mass assignment Send additional fields not in DTO
Rate Limiting Exceeding rate limits Rapid-fire requests beyond 100/min
Rate Limiting Rate limit bypass X-Forwarded-For header manipulation
Webhook Security HMAC bypass Send webhook without valid signature
Webhook Security Replay attacks Resend captured webhooks
Webhook Security Payload tampering Modify webhook body, keep old signature
Error Handling Information disclosure Trigger errors, check for stack traces
Error Handling Verbose error messages Check if internal paths are exposed
Business Logic Order state manipulation Attempt invalid state transitions
Business Logic Duplicate processing Send duplicate webhook payloads

7.4 Webhook Endpoint Testing

Webhooks are critical integration points. Test each one:

# Test Shopify webhook without HMAC
curl -X POST https://staging-connect-api.forma3d.be/api/v1/webhooks/shopify/orders/create \
  -H "Content-Type: application/json" \
  -d '{"test": true}'
# Expected: 401 or 403

# Test with invalid HMAC
curl -X POST https://staging-connect-api.forma3d.be/api/v1/webhooks/shopify/orders/create \
  -H "Content-Type: application/json" \
  -H "X-Shopify-Hmac-Sha256: invalidhash" \
  -d '{"test": true}'
# Expected: 401 or 403

# Test SimplyPrint webhook without token
curl -X POST https://staging-connect-api.forma3d.be/api/v1/webhooks/simplyprint \
  -H "Content-Type: application/json" \
  -d '{"event": "test"}'
# Expected: 401 or 403

# Test SendCloud webhook without signature
curl -X POST https://staging-connect-api.forma3d.be/api/v1/webhooks/sendcloud \
  -H "Content-Type: application/json" \
  -d '{"action": "test"}'
# Expected: 401 or 403

7.5 Schemathesis — Automated API Fuzzing

# Install
pip install schemathesis

# Run stateful API testing against Swagger spec
schemathesis run https://staging-connect-api.forma3d.be/api/docs-json \
  --stateful=links \
  --hypothesis-max-examples=100 \
  --report \
  --output schemathesis-report.html

# With authentication header
schemathesis run https://staging-connect-api.forma3d.be/api/docs-json \
  -H "X-API-Key: <internal-api-key>" \
  --stateful=links \
  --report

8. Phase 5 — Server-Side Assessment (With SSH Access)

When SSH credentials are provided, this is the most critical phase. It transitions from external testing to internal security audit.

8.1 Initial Access and Orientation

# Connect to server
ssh -i /path/to/key root@167.172.45.47

# System identification
uname -a
cat /etc/os-release
hostnamectl

8.2 System Hardening Audit

Operating System

Check Command Expected
OS version and patches apt list --upgradable 2>/dev/null \| wc -l 0 (fully patched)
Kernel version uname -r Latest stable
Automatic updates cat /etc/apt/apt.conf.d/20auto-upgrades Enabled
Running services systemctl list-units --type=service --state=running Minimal
Listening ports ss -tlnp Only 22, 80, 443
Open files lsof -i -P -n No unexpected connections
Cron jobs crontab -l; ls /etc/cron.* No suspicious entries
SUID binaries find / -perm -4000 -type f 2>/dev/null Known binaries only
World-writable files find / -perm -0002 -type f 2>/dev/null Minimal
Users with shells grep -v nologin /etc/passwd \| grep -v false Only root and necessary users

SSH Hardening

Check Where Expected
Root login /etc/ssh/sshd_config PermitRootLogin prohibit-password or no
Password auth /etc/ssh/sshd_config PasswordAuthentication no
Key-only auth /etc/ssh/sshd_config PubkeyAuthentication yes
SSH protocol /etc/ssh/sshd_config Protocol 2 only
Idle timeout /etc/ssh/sshd_config ClientAliveInterval 300
Max auth tries /etc/ssh/sshd_config MaxAuthTries 3
Allowed users /etc/ssh/sshd_config AllowUsers configured
SSH port /etc/ssh/sshd_config 22 (or non-standard)
Fail2ban systemctl status fail2ban Active and configured
SSH key strength ssh-keygen -l -f /path/to/key 4096-bit RSA or Ed25519
# Automated SSH audit
ssh-audit 167.172.45.47

# Check SSH configuration
sshd -T | grep -iE "permit|password|pubkey|protocol|maxauth|alive"

# Check authorized keys
cat ~/.ssh/authorized_keys
# Verify only expected keys are present

Firewall

# Check UFW status and rules
ufw status verbose

# Expected rules:
# 22/tcp    ALLOW IN    Anywhere
# 80/tcp    ALLOW IN    Anywhere
# 443/tcp   ALLOW IN    Anywhere

# Check iptables directly
iptables -L -n -v
ip6tables -L -n -v

# Check for unexpected ACCEPT rules

8.3 Docker Security Assessment

# Docker version and configuration
docker version
docker info

# Check Docker daemon configuration
cat /etc/docker/daemon.json
# Verify: log rotation, no insecure registries, no experimental features

# List all containers (including stopped)
docker ps -a

# Check container resource limits
docker inspect --format='{{.Name}} CPU:{{.HostConfig.NanoCpus}} MEM:{{.HostConfig.Memory}}' $(docker ps -q)

# Check container user (should not be root)
docker inspect --format='{{.Name}} User:{{.Config.User}}' $(docker ps -q)

# Check container capabilities
docker inspect --format='{{.Name}} CapAdd:{{.HostConfig.CapAdd}} CapDrop:{{.HostConfig.CapDrop}}' $(docker ps -q)

# Check mounted volumes (sensitive file exposure)
docker inspect --format='{{.Name}} Mounts:{{json .Mounts}}' $(docker ps -q) | python3 -m json.tool

# Check container networks
docker network ls
docker network inspect forma3d-network

# Check if Docker socket is mounted in any container
docker inspect --format='{{.Name}} {{range .Mounts}}{{.Source}}{{end}}' $(docker ps -q) | grep docker.sock

# Check for privileged containers
docker inspect --format='{{.Name}} Privileged:{{.HostConfig.Privileged}}' $(docker ps -q)

# Check Docker image versions for CVEs
trivy image registry.digitalocean.com/forma-3d/forma3d-connect-api:latest
trivy image registry.digitalocean.com/forma-3d/forma3d-connect-web:latest

8.4 Environment and Secrets Audit

# Check .env file permissions
ls -la /opt/forma3d/.env
# Should be 600 (owner read/write only)

# Check for secrets in environment variables of running containers
docker inspect --format='{{.Name}} {{.Config.Env}}' $(docker ps -q)
# WARNING: This exposes secrets — document but handle with care

# Check for .env files in unexpected locations
find / -name ".env" -o -name "*.env" 2>/dev/null

# Check for hardcoded credentials in Docker Compose
grep -i "password\|secret\|key\|token" /opt/forma3d/docker-compose.yml

# Check bash history for leaked secrets
cat ~/.bash_history | grep -iE "password|secret|key|token|curl.*-H"

# Check for sensitive files
find /opt/forma3d -name "*.pem" -o -name "*.key" -o -name "*.crt" 2>/dev/null
ls -la /opt/forma3d/certs/

8.5 Log Analysis

# Check authentication logs
grep "Failed password\|Invalid user\|Accepted" /var/log/auth.log | tail -50

# Check for brute force attempts
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head

# Check Docker logs for security events
docker logs forma3d-api 2>&1 | grep -iE "unauthorized|forbidden|error|fail" | tail -50

# Check Traefik access logs
docker logs forma3d-traefik 2>&1 | grep -E "4[0-9]{2}|5[0-9]{2}" | tail -50

# Check for suspicious network connections
ss -tlnp
netstat -antp 2>/dev/null

# Check system logs
journalctl --since "24 hours ago" | grep -iE "error|fail|denied|unauthorized"

8.6 Automated Server Audit Tools

Lynis (System Security Auditing)

# Install and run Lynis
apt install lynis -y
lynis audit system --quick

# Or use Docker
docker run --rm -v /:/hostroot:ro cisofy/lynis audit system --auditor "Pentest" --quick

# Review results
cat /var/log/lynis-report.dat

CIS Benchmark

# Download and run CIS benchmark scripts (Docker CIS Benchmark)
docker run --rm -it \
  --net host --pid host \
  --userns host --cap-add audit_control \
  -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
  -v /etc:/etc:ro \
  -v /usr/bin/containerd:/usr/bin/containerd:ro \
  -v /usr/bin/runc:/usr/bin/runc:ro \
  -v /usr/lib/systemd:/usr/lib/systemd:ro \
  -v /var/lib:/var/lib:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  --label docker_bench_security \
  docker/docker-bench-security

8.7 Server-Side Checklist

## Server Security Assessment Checklist

### OS Hardening

- [ ] OS fully patched and up to date
- [ ] Automatic security updates enabled
- [ ] Unnecessary services disabled
- [ ] Kernel hardening parameters set (sysctl)
- [ ] No unnecessary SUID/SGID binaries
- [ ] File permissions correctly set

### SSH

- [ ] Key-based authentication only (no password auth)
- [ ] Root login restricted
- [ ] Fail2ban or equivalent active
- [ ] SSH idle timeout configured
- [ ] Only authorized keys present
- [ ] SSH protocol 2 only

### Firewall

- [ ] UFW/iptables active
- [ ] Only ports 22, 80, 443 open
- [ ] Default deny policy
- [ ] IPv6 rules configured

### Docker

- [ ] Containers run as non-root user
- [ ] No privileged containers
- [ ] No Docker socket mounted in containers
- [ ] Resource limits configured
- [ ] Log rotation configured
- [ ] Base images scanned for CVEs
- [ ] No unnecessary capabilities

### Secrets

- [ ] .env file permissions 600
- [ ] No secrets in bash history
- [ ] No secrets in Docker Compose files (using env_file)
- [ ] No secrets in container image layers
- [ ] Certificate files properly secured

### Logging

- [ ] Auth logs monitored
- [ ] No brute force patterns detected
- [ ] Docker logs rotated
- [ ] No sensitive data in logs

9. Phase 6 — Database Security Assessment

9.1 External Assessment

The database is a DigitalOcean Managed PostgreSQL instance, not directly on the droplet.

# Verify database is NOT accessible from public internet
nmap -p 25060 db-postgresql-ams3-forma3d-staging-do-user-1196005-0.m.db.ondigitalocean.com

# Check SSL enforcement
psql "postgresql://doadmin@db-postgresql-ams3-forma3d-staging-do-user-1196005-0.m.db.ondigitalocean.com:25060/defaultdb?sslmode=disable" -c "SELECT 1"
# Should FAIL if SSL is enforced

# Check SSL connection
psql "postgresql://doadmin:<password>@db-postgresql-ams3-forma3d-staging-do-user-1196005-0.m.db.ondigitalocean.com:25060/defaultdb?sslmode=require" -c "SELECT version();"

9.2 Internal Assessment (Via SSH/Docker)

# Connect via the API container's Prisma
docker exec -it forma3d-api npx prisma db execute --stdin <<< "
  SELECT usename, usesuper, usecreatedb, passwd IS NOT NULL as has_password
  FROM pg_user;
"

# Check database roles and permissions
docker exec -it forma3d-api npx prisma db execute --stdin <<< "
  SELECT grantee, table_schema, table_name, privilege_type
  FROM information_schema.role_table_grants
  WHERE grantee NOT IN ('pg_monitor', 'pg_read_all_settings');
"

# Check for sensitive data in plain text
# (Review schema for columns that should be encrypted)
docker exec -it forma3d-api npx prisma db execute --stdin <<< "
  SELECT column_name, data_type, table_name
  FROM information_schema.columns
  WHERE column_name ILIKE '%password%'
     OR column_name ILIKE '%secret%'
     OR column_name ILIKE '%token%'
     OR column_name ILIKE '%key%';
"

9.3 Database Security Checklist

## Database Security Checklist

- [ ] SSL/TLS enforced for all connections
- [ ] Minimum privileges for application user
- [ ] No superuser access from application
- [ ] Sensitive fields encrypted at rest (tokens, OAuth data)
- [ ] Connection pooling configured (prevent connection exhaustion)
- [ ] Trusted sources / IP allowlist configured on managed DB
- [ ] Database backups enabled and tested
- [ ] No raw SQL queries (Prisma ORM only)
- [ ] pgAdmin access restricted (IP, credentials, session timeout)

10. Phase 7 — Container and Supply Chain Security

10.1 Image Security

# Verify cosign signature on images
cosign verify --key cosign.pub registry.digitalocean.com/forma-3d/forma3d-connect-api:latest
cosign verify --key cosign.pub registry.digitalocean.com/forma-3d/forma3d-connect-web:latest

# Scan images for vulnerabilities
trivy image --severity HIGH,CRITICAL registry.digitalocean.com/forma-3d/forma3d-connect-api:latest
trivy image --severity HIGH,CRITICAL registry.digitalocean.com/forma-3d/forma3d-connect-web:latest

# Check SBOM (Software Bill of Materials)
cosign verify-attestation --key cosign.pub \
  --type cyclonedx \
  registry.digitalocean.com/forma-3d/forma3d-connect-api:latest

# Analyze Dockerfile for security issues
hadolint apps/api/Dockerfile
hadolint apps/web/Dockerfile

# Check for secrets in image layers
docker history --no-trunc registry.digitalocean.com/forma-3d/forma3d-connect-api:latest
# Look for ENV/ARG with secrets

10.2 Dependency Security

# Audit npm dependencies
pnpm audit --audit-level=moderate

# Check for outdated packages
pnpm outdated

# Scan with Snyk (if available)
snyk test --all-projects

# Check for known vulnerabilities in lockfile
npm audit --json | jq '.vulnerabilities | to_entries[] | select(.value.severity == "critical" or .value.severity == "high")'

10.3 Supply Chain Checklist

## Supply Chain Security Checklist

- [ ] Container images signed with cosign
- [ ] SBOM generated and attached as attestation
- [ ] No critical/high CVEs in base images
- [ ] No critical/high CVEs in npm dependencies
- [ ] Lockfile (pnpm-lock.yaml) committed and integrity verified
- [ ] Dockerfile uses specific image tags (not :latest in production)
- [ ] Multi-stage builds used (no build tools in final image)
- [ ] Non-root user in container
- [ ] No secrets in image layers
- [ ] CI/CD pipeline integrity (branch protection, signed commits)

11. Phase 8 — Authentication and Session Testing

11.1 Login Flow Testing

Test Method Expected
Valid login POST with correct credentials 200 + session cookie
Invalid password POST with wrong password 401, no session
Empty credentials POST with empty fields 400 validation error
SQL injection in login ' OR 1=1-- in email field 400/401, no bypass
Brute force (10 attempts) Rapid login attempts Rate limited after N
Account lockout 20+ failed attempts Account locked or increasing delays
Session cookie attributes Inspect Set-Cookie header Secure, HttpOnly, SameSite=Lax/Strict
Session fixation Check if session ID changes after login New session ID issued
Session timeout Wait beyond SESSION_MAX_AGE_DAYS Session expired
Concurrent sessions Login from two browsers Both valid or old one invalidated
Logout POST to logout endpoint Session cookie cleared/invalidated

11.2 API Key Testing

Test Method Expected
Valid API key X-API-Key: valid-key 200
Missing API key No header 401
Invalid API key X-API-Key: invalid 401
Expired/rotated key Old API key 401
Key in URL ?api_key=value Should NOT work (header only)
Key bruteforce Rapid attempts with random keys Rate limited

12. Phase 9 — Business Logic Testing

12.1 Order Flow Testing

Test Description Risk
Order state manipulation Attempt to move order from DELIVERED back to PENDING Data integrity
Duplicate order creation Send same webhook twice rapidly Financial impact
Price manipulation Modify order amounts in transit Financial impact
Order for another tenant Access orders belonging to different shop Data breach
Mass order creation Flood system with fake orders DoS

12.2 Print Job Flow Testing

Test Description Risk
Job cancellation race Cancel while printing starts State corruption
Job assignment to wrong printer Manipulate printer IDs Business disruption
File upload manipulation If applicable, upload non-STL files System compromise

12.3 Webhook Replay and Timing

Test Description Risk
Webhook replay attack Resend captured Shopify webhook Duplicate processing
Webhook timing attack Send many webhooks simultaneously Race conditions
Out-of-order webhooks Send fulfillment before order create Logic errors
Idempotency bypass Modify idempotency key Duplicate processing

13. Toolchain Reference

13.1 Essential Tools (Free / Open Source)

Tool Category Purpose Install
nmap Network Port scanning, service detection apt install nmap
testssl.sh TLS Comprehensive TLS testing git clone https://github.com/drwetter/testssl.sh
OWASP ZAP Web App Web vulnerability scanner docker pull zaproxy/zap-stable
Nuclei Multi Template-based vulnerability scanner go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
ffuf Web App Web fuzzer / directory brute force go install github.com/ffuf/ffuf/v2@latest
sqlmap Injection SQL injection testing pip install sqlmap
nikto Web Server Web server vulnerability scanner apt install nikto
Trivy Container Image vulnerability scanner apt install trivy
Lynis System Security auditing apt install lynis
subfinder Recon Subdomain enumeration go install github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
httpx Recon HTTP probing go install github.com/projectdiscovery/httpx/cmd/httpx@latest
Schemathesis API Property-based API testing pip install schemathesis
ssh-audit SSH SSH configuration auditing pip install ssh-audit
cosign Supply Chain Container signing verification go install github.com/sigstore/cosign/v2/cmd/cosign@latest
hadolint Container Dockerfile linter docker pull hadolint/hadolint
dalfox XSS XSS scanner go install github.com/hahwul/dalfox/v2@latest
docker-bench-security Container CIS Docker Benchmark Docker image
theHarvester OSINT Email/subdomain harvesting pip install theHarvester
amass Recon Subdomain enumeration go install github.com/owasp-amass/amass/v4/...@master
Tool Category Purpose Cost
Burp Suite Professional Web/API Comprehensive web testing proxy ~$449/year
Nessus Professional Vulnerability Network vulnerability scanner ~$3,590/year
Snyk Dependencies Dependency and container scanning Free tier available
Metasploit Pro Exploitation Exploitation framework ~$15,000/year

13.3 Kali Linux — Pre-Built Pentest Environment

For a self-contained pentest lab, use Kali Linux which includes most tools pre-installed:

# Run Kali as Docker container for quick testing
docker run -it --rm kalilinux/kali-rolling /bin/bash
apt update && apt install -y kali-tools-web kali-tools-information-gathering

# Or use a Kali VM for full GUI tools
# Download from: https://www.kali.org/get-kali/

14. Report Deliverables

14.1 Report Types

A complete penetration test produces the following deliverables:

Report Audience Contents
Executive Summary (2-3 pages) Management, CTO Risk overview, critical findings, business impact, compliance status
Technical Report (20-50 pages) Development team Detailed findings, reproduction steps, evidence, remediation guidance
Vulnerability Register (Spreadsheet) Project management All findings with CVSS scores, status tracking, assignment
NIS2 Compliance Gap Analysis Compliance officer Mapping of findings to NIS2 requirements
Remediation Roadmap Engineering lead Prioritized fix plan with effort estimates
Retest Report (after fixes) All stakeholders Verification that vulnerabilities are resolved

14.2 Finding Classification (CVSS 3.1)

Severity CVSS Score SLA to Fix Example
Critical 9.0 - 10.0 24-48 hours RCE, SQL injection, auth bypass
High 7.0 - 8.9 7 days Privilege escalation, sensitive data exposure
Medium 4.0 - 6.9 30 days XSS, CSRF, information disclosure
Low 0.1 - 3.9 90 days Missing headers, verbose errors
Informational 0.0 Best effort Best practice recommendations

14.3 Individual Finding Template

Each finding should be documented using this structure:

## Finding: [VULN-001] [Title]

### Metadata

| Field          | Value                                 |
| -------------- | ------------------------------------- |
| Severity       | Critical / High / Medium / Low / Info |
| CVSS Score     | X.X                                   |
| CVSS Vector    | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H   |
| OWASP Category | A01:2021 Broken Access Control        |
| Status         | Open / Remediated / Accepted Risk     |
| Affected Asset | staging-connect-api.forma3d.be        |
| CWE            | CWE-XXX                               |

### Description

[Clear description of the vulnerability]

### Impact

[Business impact if exploited]

### Steps to Reproduce

1. [Step 1]
2. [Step 2]
3. [Step 3]

### Evidence

[Screenshots, request/response pairs, tool output]

### Remediation

**Recommended Fix:**
[Specific code or configuration change]

**Alternative Mitigations:**
[Temporary workarounds if immediate fix is not possible]

### References

- [Link to CWE]
- [Link to OWASP reference]

14.4 Executive Summary Template

# Penetration Test — Executive Summary

**Client:** Forma 3D / DevGem  
**Target:** Forma 3D Connect Staging Environment  
**Date:** [Test Date]  
**Tester:** [Name/Organization]  
**Classification:** Confidential

## Overall Risk Rating: [Critical / High / Medium / Low]

## Scope

- Web application, REST API, DNS, server infrastructure (with SSH access)

## Summary of Findings

| Severity      | Count |
| ------------- | ----- |
| Critical      | X     |
| High          | X     |
| Medium        | X     |
| Low           | X     |
| Informational | X     |
| **Total**     | **X** |

## Top 3 Critical Findings

1. [Finding title and brief impact]
2. [Finding title and brief impact]
3. [Finding title and brief impact]

## Key Recommendations

1. [Top priority action]
2. [Second priority action]
3. [Third priority action]

## NIS2 Compliance Status

[Brief assessment of compliance posture]

## Next Steps

- [ ] Remediate critical and high findings within SLA
- [ ] Schedule retest in [X] weeks
- [ ] Update security documentation

15. NIS2 Compliance Evaluation

15.1 What is NIS2?

The Network and Information Security Directive 2 (NIS2) — EU Directive 2022/2555 — is the EU's updated cybersecurity legislation that came into force on January 16, 2023 with member state transposition deadline of October 17, 2024. It significantly expands the scope and requirements of the original NIS Directive.

15.2 Does NIS2 Apply to Forma 3D Connect?

NIS2 applies to essential and important entities. Even if Forma 3D is not directly classified as such, it may fall under NIS2 if:

  • It provides services to entities that are classified (supply chain obligations)
  • It operates as a digital infrastructure or digital service provider
  • Belgian national implementation (the "NIS2 wet") may have broader scope

Assessment: As a B2B SaaS platform handling e-commerce order fulfillment, Forma 3D Connect likely falls under "important entity" as a digital service provider, depending on revenue and employee thresholds. Regardless, adopting NIS2 measures is a competitive advantage and aligns with customer expectations.

15.3 NIS2 Article 21 — Security Measures Mapping

Article 21 defines the minimum cybersecurity risk-management measures. Here is how to evaluate each during a penetration test:

NIS2 Requirement (Art. 21.2) What to Test How to Evaluate Current Status
(a) Risk analysis and information system security policies Security policies documented? Risk register maintained? Review documentation, interview team Check docs/ folder, security-audit-checklist.md
(b) Incident handling Incident response plan exists? Tested? Review IR procedures, check Sentry alerting Check disaster-recovery-research.md
© Business continuity and crisis management Backup and DR plans? Tested? Review backup procedures, RPO/RTO defined Check disaster-recovery-research.md
(d) Supply chain security Third-party risk assessed? Dependencies audited? Check cosign, SBOM, dependency scanning Cosign signing, pnpm audit
(e) Security in network and information systems acquisition, development and maintenance Secure SDLC? Code review? Testing? Review CI/CD pipeline, security gates Azure DevOps pipeline, lint/test gates
(f) Policies and procedures for assessing effectiveness of cybersecurity risk-management measures Regular pentests? Audits? Metrics? This pentest itself evaluates this This document
(g) Basic cyber hygiene practices and cybersecurity training Developer security training? Secure coding practices? Interview team, review .cursorrules .cursorrules enforces secure patterns
(h) Policies and procedures regarding the use of cryptography and encryption Encryption at rest and transit? Key management? Test TLS, check token encryption, review key management TLS via Traefik, AES-256-GCM for tokens
(i) Human resources security, access control policies and asset management RBAC? Least privilege? Asset inventory? Test authorization, review access controls RBAC implemented, keys-certificates-inventory.md
(j) Use of multi-factor authentication or continuous authentication solutions MFA implemented? SSO? Test authentication flow Evaluate current auth mechanism

15.4 NIS2 Compliance Evaluation Checklist

## NIS2 Compliance Evaluation

### Governance and Risk Management

- [ ] Information security policy documented and approved
- [ ] Risk assessment methodology defined
- [ ] Risk register maintained and regularly updated
- [ ] Management accountability for cybersecurity (board-level)
- [ ] Security roles and responsibilities defined

### Incident Handling (Art. 21.2b + Art. 23)

- [ ] Incident response plan documented
- [ ] Incident classification scheme (severity levels)
- [ ] 24-hour early warning to CSIRT for significant incidents
- [ ] 72-hour incident notification with initial assessment
- [ ] 1-month final report for significant incidents
- [ ] Incident response team identified
- [ ] Incident response tested (tabletop or simulation)
- [ ] Contact details for national CSIRT known (Belgium: CCB/CERT.be)

### Business Continuity (Art. 21.2c)

- [ ] Business continuity plan documented
- [ ] Backup strategy implemented and tested
- [ ] Recovery Time Objective (RTO) defined
- [ ] Recovery Point Objective (RPO) defined
- [ ] Disaster recovery procedures documented
- [ ] Business continuity plan tested annually

### Supply Chain Security (Art. 21.2d)

- [ ] Third-party risk assessment for critical suppliers
- [ ] Security requirements in supplier contracts
- [ ] SBOM (Software Bill of Materials) generated
- [ ] Container images signed (cosign)
- [ ] Dependency vulnerability scanning automated
- [ ] Supplier security incidents monitored

### Secure Development (Art. 21.2e)

- [ ] Secure coding guidelines documented (.cursorrules)
- [ ] Code review process in place
- [ ] Automated security testing in CI/CD (SAST)
- [ ] Vulnerability disclosure process defined
- [ ] Patch management process defined
- [ ] Change management process documented

### Security Assessment (Art. 21.2f)

- [ ] Regular penetration testing (at least annually)
- [ ] Vulnerability scanning (at least quarterly)
- [ ] Security metrics tracked (MTTD, MTTR)
- [ ] Audit trail maintained
- [ ] Findings tracked to remediation

### Cyber Hygiene (Art. 21.2g)

- [ ] Security awareness training for all team members
- [ ] Secure password policy enforced
- [ ] Phishing awareness
- [ ] Clean desk / clean screen policy
- [ ] Device management policy

### Cryptography (Art. 21.2h)

- [ ] Encryption policy documented
- [ ] TLS 1.2+ enforced for all communications
- [ ] Sensitive data encrypted at rest
- [ ] Key management procedures documented
- [ ] Certificate lifecycle management
- [ ] Cryptographic key rotation schedule

### Access Control (Art. 21.2i)

- [ ] Role-based access control (RBAC) implemented
- [ ] Least privilege principle enforced
- [ ] User access regularly reviewed
- [ ] Privileged access management
- [ ] Asset inventory maintained
- [ ] Offboarding process revokes all access

### Authentication (Art. 21.2j)

- [ ] Multi-factor authentication for administrative access
- [ ] MFA for remote access (SSH, VPN)
- [ ] Strong password requirements enforced
- [ ] Session management secure (timeout, invalidation)
- [ ] API authentication using secure methods (not basic auth)

15.5 NIS2 Reporting Obligations

If a significant incident occurs, NIS2 requires strict reporting timelines:

                    Incident Detected
                           │
                           ▼
              ┌────────────────────────┐
              │  24 Hours: Early       │
              │  Warning to CSIRT      │──── "Is this a significant incident?"
              │  (Belgium: CCB)        │     Cross-border impact? Large-scale?
              └────────────┬───────────┘
                           │
                           ▼
              ┌────────────────────────┐
              │  72 Hours: Incident    │
              │  Notification          │──── Initial assessment, severity,
              │  + Initial Assessment  │     impact, IoCs
              └────────────┬───────────┘
                           │
                           ▼
              ┌────────────────────────┐
              │  1 Month: Final        │
              │  Report                │──── Root cause, remediation,
              │                        │     cross-border impact
              └────────────────────────┘

Belgium-specific: The Centre for Cybersecurity Belgium (CCB) is the competent authority. Report via https://ccb.belgium.be.

15.6 NIS2 Gap Analysis Template

# NIS2 Requirement Current Maturity Gap Priority Remediation
1 Risk analysis policy Partial — docs exist but no formal policy Need formal security policy signed by management High Draft and approve security policy document
2 Incident handling Partial — Sentry + DR doc exist Need formal IR plan, CSIRT contact, reporting procedures Critical Create IR plan, register with CCB
3 Business continuity Good — DR research completed Need regular testing of backups Medium Schedule quarterly backup restore test
4 Supply chain security Good — cosign, SBOM, pnpm audit Need formal supplier risk assessment Medium Create supplier security questionnaire
5 Secure development Good — CI/CD with tests, .cursorrules SBOM + CVE scanning via Syft/Grype; SonarCloud for SAST Low Verify SonarCloud security hotspot coverage
6 Security assessment effectiveness Starting — this research document Need regular pentest schedule High Schedule annual pentest
7 Cyber hygiene training Unknown Need training program High Implement security awareness training
8 Cryptography policy Partial — TLS + encryption implemented Need documented encryption policy Medium Document encryption standards
9 Access control Good — RBAC implemented Need access review process Medium Implement quarterly access reviews
10 MFA Not implemented Critical gap for admin access Critical Implement MFA for all admin accounts

16.1 Annual Testing Calendar

Quarter Activity Scope Type
Q1 (Jan-Mar) Full penetration test All targets, including SSH External + Internal
Q2 (Apr-Jun) Automated vulnerability scan Web, API, containers Automated
Q3 (Jul-Sep) Focused retest + new features Changed components Targeted
Q4 (Oct-Dec) Automated scan + NIS2 audit Full scope + compliance Automated + Audit

16.2 Trigger-Based Testing

Additional testing should occur when:

Trigger Testing Scope
Major release Affected endpoints and features
New integration added Integration security + webhooks
Infrastructure change Server and network assessment
Security incident Full scope retest
After NIS2 audit finding Specific remediation verification

17. Cost Estimates and Vendor Options

17.1 DIY Pentest (Internal)

Item Cost Notes
Burp Suite Professional ~$449/year Essential tool
Kali Linux VM Free Pre-installed tools
Time investment 40-80 hours Depending on depth
Total ~$449 + labor

Pros: Deep system knowledge, immediate findings, repeatable Cons: Potential blind spots, less credible for compliance, time-intensive

17.2 External Pentest (Vendor)

Vendor Type Cost Range Duration Includes
Freelance pentester EUR 3,000-8,000 5-10 days Web + API + server
Boutique security firm (BE) EUR 8,000-15,000 10-15 days Full scope + NIS2 mapping
Big 4 / large consultancy EUR 20,000-50,000 15-25 days Full scope + compliance + governance

Belgian pentest firms to consider:

  • Toreon (Leuven) — well-known Belgian security firm
  • NVISO (Brussels) — specializes in penetration testing and red teaming
  • Secure Code Warrior (Brussels) — developer security training + assessment
  • BeSafe (Antwerp) — SME-focused security assessments
  • Approach (Brussels) — NIS2 compliance specialists
Phase Who Cost Frequency
Automated scanning Internal (Nuclei, Trivy, pnpm audit) Free Continuous/Weekly
Manual web/API test Internal (Burp Suite) ~$449/year Quarterly
Full external pentest Belgian security firm ~EUR 8,000-12,000 Annually
NIS2 gap analysis Compliance consultant ~EUR 3,000-5,000 Annually
Annual Total ~EUR 12,000-18,000

Appendix A: Quick-Start Commands

A.1 External Scan (No Credentials)

Run these from your local machine or a Kali Linux VM:

#!/bin/bash
# quick-external-scan.sh
# Non-intrusive external scan of staging environment

TARGET_API="staging-connect-api.forma3d.be"
TARGET_WEB="staging-connect.forma3d.be"
TARGET_DB="staging-connect-db.forma3d.be"
TARGET_IP="167.172.45.47"
OUTPUT_DIR="pentest-results-$(date +%Y%m%d)"

mkdir -p $OUTPUT_DIR

echo "=== Phase 1: DNS ==="
dig forma3d.be ANY > $OUTPUT_DIR/dns-any.txt
dig axfr forma3d.be @$(dig NS forma3d.be +short | head -1) > $OUTPUT_DIR/dns-axfr.txt 2>&1
dig _dmarc.forma3d.be TXT > $OUTPUT_DIR/dns-dmarc.txt
dig forma3d.be TXT > $OUTPUT_DIR/dns-txt.txt
dig forma3d.be CAA > $OUTPUT_DIR/dns-caa.txt

echo "=== Phase 2: Port Scan ==="
nmap -sS -sV -sC -p- -oA $OUTPUT_DIR/nmap-full $TARGET_IP

echo "=== Phase 3: TLS ==="
testssl.sh --html $TARGET_API > $OUTPUT_DIR/tls-api.html
testssl.sh --html $TARGET_WEB > $OUTPUT_DIR/tls-web.html

echo "=== Phase 4: Security Headers ==="
curl -sI https://$TARGET_API/health > $OUTPUT_DIR/headers-api.txt
curl -sI https://$TARGET_WEB > $OUTPUT_DIR/headers-web.txt
curl -sI https://$TARGET_DB > $OUTPUT_DIR/headers-pgadmin.txt

echo "=== Phase 5: Nuclei ==="
nuclei -u https://$TARGET_API -o $OUTPUT_DIR/nuclei-api.txt
nuclei -u https://$TARGET_WEB -o $OUTPUT_DIR/nuclei-web.txt
nuclei -u https://$TARGET_DB -o $OUTPUT_DIR/nuclei-pgadmin.txt

echo "=== Phase 6: Directory Discovery ==="
ffuf -w /usr/share/seclists/Discovery/Web-Content/common.txt \
  -u https://$TARGET_API/FUZZ -mc 200,301,302,403 \
  -o $OUTPUT_DIR/ffuf-api.json -of json

echo "=== Scan complete. Results in $OUTPUT_DIR ==="

A.2 Server Audit (With SSH)

#!/bin/bash
# quick-server-audit.sh
# Run on the droplet after SSH access

OUTPUT_DIR="/tmp/audit-$(date +%Y%m%d)"
mkdir -p $OUTPUT_DIR

echo "=== System Info ==="
uname -a > $OUTPUT_DIR/system-info.txt
cat /etc/os-release >> $OUTPUT_DIR/system-info.txt

echo "=== Open Ports ==="
ss -tlnp > $OUTPUT_DIR/open-ports.txt

echo "=== Running Services ==="
systemctl list-units --type=service --state=running > $OUTPUT_DIR/services.txt

echo "=== Firewall ==="
ufw status verbose > $OUTPUT_DIR/firewall.txt

echo "=== SSH Config ==="
sshd -T 2>/dev/null > $OUTPUT_DIR/ssh-config.txt

echo "=== Docker Containers ==="
docker ps -a > $OUTPUT_DIR/docker-containers.txt
docker images > $OUTPUT_DIR/docker-images.txt

echo "=== Docker Security ==="
for container in $(docker ps -q); do
  name=$(docker inspect --format='{{.Name}}' $container)
  echo "--- $name ---" >> $OUTPUT_DIR/docker-security.txt
  docker inspect --format='User:{{.Config.User}} Privileged:{{.HostConfig.Privileged}} CapAdd:{{.HostConfig.CapAdd}}' $container >> $OUTPUT_DIR/docker-security.txt
done

echo "=== .env Permissions ==="
ls -la /opt/forma3d/.env > $OUTPUT_DIR/env-permissions.txt

echo "=== Updatable Packages ==="
apt list --upgradable 2>/dev/null > $OUTPUT_DIR/updatable-packages.txt

echo "=== SUID Binaries ==="
find / -perm -4000 -type f 2>/dev/null > $OUTPUT_DIR/suid-binaries.txt

echo "=== Failed Auth (Last 50) ==="
grep "Failed password\|Invalid user" /var/log/auth.log 2>/dev/null | tail -50 > $OUTPUT_DIR/failed-auth.txt

echo "=== Audit complete. Results in $OUTPUT_DIR ==="

Appendix B: Belgian NIS2 Contacts

Entity Role Contact
Centre for Cybersecurity Belgium (CCB) National authority https://ccb.belgium.be
CERT.be National CSIRT https://cert.be
NIS2 Notification Portal Incident reporting https://nis2.belgium.be (when available)
Belgian DPA (GBA/APD) Data protection (GDPR + NIS2 overlap) https://www.gegevensbeschermingsautoriteit.be

Appendix C: References


Document Version: 1.0
Last Updated: February 2026
Next Review: August 2026