← Portfolio

Projet personnel · 09/2026

Audit de sécurité de djuju02.fr

Ce site est en production : portfolio, overlays de stream, bots Twitch et Discord, webhooks ouverts sur Internet et console d'administration, sur un hébergement mutualisé. Je l'ai audité en boîte blanche, puis j'ai corrigé et vérifié chaque constat.

Réalisé avec une assistance d'IA.

Périmètre et méthode

Code

Chaque point d'entrée relu : authentification, CSRF, échappement des sorties, envois de fichiers, lectures de fichiers, requêtes sortantes, webhooks, OAuth, et manipulation du DOM en JavaScript.

Historique Git

Tous les commits parcourus à la recherche de secrets. Un secret retiré du code reste lisible dans les versions précédentes.

Production

Tests passifs uniquement : en-têtes, cookies, fichiers sensibles, listage des dossiers, méthodes HTTP. Ni force brute, ni saturation.

Constats et correctifs

  1. Moyenne

    Clé d'administration acceptée dans l'URL

    Deux outils internes acceptaient la clé en paramètre d'URL : aucune limite de tentatives, et la clé restait lisible dans les journaux du serveur et l'historique du navigateur.

    Correctif : Session d'administration exigée, avec jeton CSRF pour chaque action.

  2. Moyenne

    Sessions privilégiées sans expiration

    Une session d'administration restait valide tant que le cookie existait : aucune limite côté serveur.

    Correctif : Expiration après 2 h d'inactivité et 12 h au maximum ; purge des sessions périmées.

  3. Moyenne

    HSTS absent

    Une première visite en HTTP pouvait être interceptée avant la redirection vers HTTPS.

    Correctif : En-tête Strict-Transport-Security activé pour un an.

  4. Faible

    Interactions Discord rejouables

    La signature Ed25519 était vérifiée, mais pas l'horodatage signé : une requête interceptée restait valable indéfiniment.

    Correctif : Fenêtre de validité de 5 minutes.

  5. Faible

    Téléchargement distant non contrôlé

    Des images récupérées depuis une URL externe étaient écrites dans le dossier public sans contrôle du domaine, de la taille ni du contenu.

    Correctif : HTTPS vers le CDN Twitch uniquement, 2 Mo au maximum, signature JPEG ou PNG vérifiée.

  6. Faible

    Déconnexion sans jeton CSRF

    Un site tiers pouvait déconnecter un administrateur à son insu.

    Correctif : Jeton CSRF exigé sur toutes les pages concernées.

  7. Faible

    Code d'accès trop court

    Un espace privé acceptait un code de 8 caractères, protégé seulement par un verrou par adresse IP, que l'on contourne en changeant d'adresse.

    Correctif : Longueur minimale portée à 12 caractères.

  8. Info

    Serveur de déploiement non authentifié

    Sans empreinte connue, le déploiement SFTP acceptait la clé présentée par le serveur à chaque exécution.

    Correctif : Empreinte du serveur vérifiée hors ligne et figée dans un secret GitHub.

  9. Info

    Port explicite dans les redirections

    Certaines redirections sortaient en « :443 ». Sans risque, mais signe de règles de réécriture imprécises.

    Correctif : Cibles de redirection absolues, sans port.

Vérification

Chaque correctif a été éprouvé en local avant la mise en ligne. Par exemple, une interaction Discord correctement signée mais datée de 15 minutes est refusée, et une déconnexion forgée depuis un autre site reste sans effet.

Puis en production : HSTS présent, clé passée dans l'URL refusée, pages principales toujours accessibles.

Ce qui était déjà solide

  • Content Security Policy stricte, sans unsafe-inline ni unsafe-eval, et aucune donnée externe insérée comme HTML.
  • Toutes les sorties PHP échappées, données structurées JSON-LD comprises.
  • Jeton CSRF sur chaque formulaire qui modifie des données.
  • Webhooks Twitch (HMAC-SHA256) et Discord (Ed25519) vérifiés en temps constant, avec déduplication des messages Twitch.
  • Jetons OAuth chiffrés en AES-256-GCM ; secrets hors du dépôt et hors du dossier public.
  • Fichiers envoyés contrôlés sur leur contenu réel et stockés hors du dossier public.
  • Formulaire de contact limité en fréquence et protégé contre l'injection d'en-têtes d'e-mail.

Empêcher la régression

Un correctif ne vaut que s'il survit aux modifications suivantes. Chaque mise en ligne passe désormais par GitHub Actions, et le moindre échec bloque le déploiement.

Avant l'envoi

  • Scan de tout l'historique avec gitleaks
  • Aucun script, style ou gestionnaire d'événement en ligne
  • Aucune insertion de HTML en JavaScript
  • CSP jamais affaiblie
  • Fichiers compilés identiques à leurs sources

Chaîne d'approvisionnement

  • Actions GitHub figées par empreinte de commit
  • Jeton GitHub en lecture seule
  • Outils téléchargés vérifiés par SHA-256
  • Secrets transmis par l'environnement, jamais insérés dans le script

Après l'envoi

  • En-têtes de sécurité présents
  • Redirection HTTP vers HTTPS
  • Fichiers de configuration et secrets inaccessibles

Limites

Hors périmètre : la résistance aux attaques par saturation, les tentatives de force brute, et la configuration du compte chez l'hébergeur. La bibliothèque embarquée (React 18.3.1) a été vérifiée après coup : aucune vulnérabilité connue ne la concerne.