Rapport d'audit de sécurité — SFER

Application Laravel 11  ·  Analyse statique complète (général + espace admin)  ·  2 mai 2026  ·  19 failles identifiées

5
Critique
6
Haute
5
Moyenne
2
Faible
19
Total
11
Failles spécifiques admin (/cp-admin/)
8
Failles générales (app publique + config)
Actions immédiates requises avant toute mise en production

(A1) Supprimer les lignes Log::info qui loggent la clé secrète 2FA et le code OTP — risque de compromission totale du 2FA admin.  (S1) Désactiver les routes /debug/*.  (S3) Retirer les clés Stripe PROD du fichier .env local.


Partie Admin — Failles spécifiques (/cp-admin/)

Authentification, gestion des permissions, fichiers de configuration, logs.

Critique

2 failles
A1 — Clé secrète 2FA loggée en clair dans les logs Laravel Critique
Fichier concerné
app/Http/Controllers/Admin/Auth/Admin2FAController.php (~ligne 90)
Description
Lors de l'activation du 2FA, la clé secrète TOTP brute (secret_key) est écrite dans les logs Laravel via Log::info(). C'est le seed qui génère TOUS les codes OTP futurs. Quiconque accède au fichier storage/logs/laravel-*.log peut usurper le 2FA de n'importe quel admin.
Exploitation
Accès au fichier de log → extraire le secret_key → le charger dans une app TOTP (Google Authenticator, etc.) → générer des codes valides à volonté pour contourner le 2FA de n'importe quel admin.
Correction recommandée
Supprimer immédiatement cette ligne de log. Ne jamais logger une clé cryptographique. Aussi purger les logs existants qui contiennent déjà ces clés.
A2 — Code TOTP loggué en clair lors de chaque vérification 2FA Critique
Fichier concerné
app/Http/Controllers/Admin/Auth/AdminLoginController.php (~ligne 169)
Description
À chaque tentative de vérification 2FA, le code OTP saisi est loggué : Log::info('Login 2FA Verification', ['code' => $code, ...]). Un code TOTP est valide ~30 secondes. Si les logs sont surveillés, le code peut être réutilisé pour une connexion parallèle.
Exploitation
Monitoring des logs en temps réel → récupérer le code OTP valide dans les 30 secondes → l'utiliser sur un autre navigateur pour contourner le 2FA.
Correction recommandée
Supprimer tous les Log::info contenant le code OTP dans AdminLoginController et Admin2FAController. Nettoyer les logs existants.

Haute

4 failles
A3 — Path Traversal dans updateTranslations() et deleteTranslationKey() Haute
Fichier concerné
app/Http/Controllers/Admin/SettingsController.php (~lignes 564 et 672)
Description
Le champ "file" est validé avec 'required|string' sans regex restrictif. Un admin peut passer "../../config/database" comme nom de fichier pour écraser ou lire des fichiers PHP de configuration critiques hors du dossier lang/.
Exploitation
POST /cp-admin/settings/update-translations avec file="../../config/database" écrase config/database.php avec un contenu arbitraire.
Correction recommandée
Ajouter 'regex:/^[a-zA-Z0-9_\/-]+$/' sur le champ "file" et vérifier que realpath($filePath) commence par realpath(base_path("lang/")).
A4 — Path Traversal dans deleteTranslationFile() Haute
Fichier concerné
app/Http/Controllers/Admin/SettingsController.php (~ligne 756)
Description
deleteTranslationFile() valide "filename" avec 'required|string' uniquement, sans regex (contrairement à createTranslationFile() qui a un regex strict). Un admin peut supprimer n'importe quel fichier .php accessible.
Exploitation
POST avec filename="../../bootstrap/app" supprime bootstrap/app.php, rendant l'application inaccessible.
Correction recommandée
Ajouter 'regex:/^[a-zA-Z0-9_\/-]+$/' sur "filename" et une vérification realpath().
A5 — Route /clear-cache accessible à tous les admins (sans restriction de rôle) Haute
Fichier concerné
routes/admin.php (~ligne 199)
Description
La route POST /cp-admin/clear-cache exécute cache:clear, config:clear, route:clear et view:clear sans middleware de rôle. Elle est dans la section "ROUTES SYSTÈME" accessible à tout admin authentifié, pas seulement super_admin.
Exploitation
Un admin avec le rôle le plus bas peut vider le cache de configuration à tout moment.
Correction recommandée
Déplacer cette route dans le groupe middleware(['role:super_admin']).
A6 — Route de simulation d'inscription admin toujours active Haute
Fichier concerné
routes/admin.php (/cp-admin/simulate-visitor-registration)
Description
Une route de test crée de vraies inscriptions en base de données avec un User::find(6673) hardcodé. Elle est accessible à tous les admins connectés et envoie de vraies notifications.
Exploitation
Tout admin peut déclencher de fausses inscriptions, polluant les statistiques et déclenchant de vrais emails de confirmation.
Correction recommandée
Supprimer cette route avant tout déploiement en production.

Moyenne

3 failles
A7 — Méthode testVerification() de debug laissée dans le code Moyenne
Fichier concerné
app/Http/Controllers/Admin/Auth/Admin2FAController.php (fin du fichier)
Description
La méthode testVerification() est une route de debug qui révèle l'implémentation interne du 2FA. Elle n'est pas enregistrée dans les routes actuellement mais reste dans le code et pourrait être activée accidentellement.
Exploitation
Si enregistrée accidentellement, permet à tout admin d'obtenir des informations sur l'implémentation interne du 2FA.
Correction recommandée
Supprimer complètement cette méthode du code.
A8 — Logs de debug 2FA extrêmement verbeux en production Moyenne
Fichier concerné
app/Http/Controllers/Admin/Auth/ (AdminLoginController + Admin2FAController)
Description
Les deux contrôleurs produisent des dizaines de Log::info à chaque login/vérification 2FA, incluant emails admin, résultats internes, traces. Avec LOG_LEVEL=debug, les logs grossissent rapidement et constituent une mine d'informations.
Exploitation
Exfiltration des logs → reconstruction du comportement de l'authentification et des métadonnées des comptes admin.
Correction recommandée
Supprimer tous les Log::info de debug. Garder uniquement Log::warning et Log::error pour les événements anormaux. Passer LOG_LEVEL=warning en production.
A9 — viewEmailHtml retourne du HTML brut non sanitisé (XSS potentiel) Moyenne
Fichier concerné
app/Http/Controllers/Admin/UsersController.php (méthode viewEmailHtml)
Description
La méthode retourne response($emailLog->html_content) avec Content-Type: text/html sans sanitisation. Si le contenu HTML contient du JavaScript (XSS stocké), il s'exécutera dans le navigateur de l'admin consultant l'email.
Exploitation
Email de contact malveillant contenant du JavaScript → exécution de code dans le contexte admin lors de la consultation de cet email dans le panneau admin.
Correction recommandée
Ajouter un Content-Security-Policy restrictif sur cette réponse (script-src 'none'), ou servir le contenu dans un iframe sandboxé.

Faible

1 faille
A10 — Redirection post-login admin vérifiée avec un mauvais préfixe Faible
Fichier concerné
app/Http/Controllers/Admin/Auth/AdminLoginController.php (sendLoginResponse)
Description
La vérification de sécurité utilise '/admin/' comme préfixe alors que l'interface admin est sous '/cp-admin/'. La condition ne sera jamais vraie : le redirect "intended" ne fonctionne jamais.
Exploitation
Pas directement exploitable — mais révèle un code de sécurité non testé et non fonctionnel (la fonctionnalité est silencieusement cassée).
Correction recommandée
Corriger en : str_starts_with($intended, request()->getSchemeAndHttpHost() . '/cp-admin/')

Failles générales

Failles dans l'application publique, la configuration, les paiements et l'espace membre.

Critique

3 failles
S1 — Routes /debug/* publiques sans authentification Critique
Fichier concerné
routes/web.php (bas du fichier — groupe prefix('debug'))
Description
Les routes /debug/users, /debug/registrations, /debug/trainings, /debug/teams, /debug/trainingimages, /debug/pushes exposent toutes les données sensibles sans aucune protection. Le commentaire "to comment in production" indique que ce code n'a jamais été désactivé.
Exploitation
N'importe qui peut accéder à /debug/users et obtenir la liste complète des membres avec leurs données personnelles (RGPD), ou /debug/registrations pour voir toutes les inscriptions et montants payés.
Correction recommandée
Commenter ou supprimer le groupe Route::prefix('debug') avant tout déploiement en production.
S2 — APP_DEBUG=true Critique
Fichier concerné
.env
Description
Le mode debug est activé. En production, cela expose des stack traces complètes, les variables d'environnement, la structure de la base de données et les chemins internes du serveur lors de toute erreur PHP.
Exploitation
Provoquer délibérément une erreur (ex: soumettre une valeur invalide) pour obtenir une page d'erreur Laravel détaillant toute la configuration interne.
Correction recommandée
Passer APP_DEBUG=false et APP_ENV=production sur le serveur de production.
S3 — Clés Stripe PRODUCTION présentes dans .env (commentées) Critique
Fichier concerné
.env (lignes sk_live_* et pk_live_*)
Description
Les clés secrètes Stripe de production (sk_live_51LDO6V... et pk_live_51LDO6V...) ainsi que le webhook secret PROD sont présentes dans le .env local, même commentées. Si ce fichier est exposé ou versionné accidentellement, les clés PROD sont compromises.
Exploitation
Un attaquant qui accède au .env peut décommenter et utiliser les clés PROD pour facturer des clients réels ou accéder aux données de paiement.
Correction recommandée
Retirer complètement les clés de production du .env local. Les stocker uniquement sur le serveur de production via variables d'environnement système ou gestionnaire de secrets.

Haute

2 failles
S4 — Credentials base de données : root sans mot de passe Haute
Fichier concerné
.env (DB_USERNAME=root, DB_PASSWORD=)
Description
Le compte root MySQL sans mot de passe est utilisé pour l'application. En cas de compromission d'une autre application sur le même serveur, toutes les bases de données sont accessibles.
Exploitation
Toute application ou script PHP sur le même serveur peut se connecter à MySQL avec root/vide et accéder à toutes les données.
Correction recommandée
Créer un utilisateur MySQL dédié avec un mot de passe fort et des permissions limitées à la seule base sfer. Ne jamais utiliser root pour les applications web.
S5 — SESSION_ENCRYPT=false Haute
Fichier concerné
.env
Description
Les données de session stockées en base de données ne sont pas chiffrées. Si un attaquant accède à la table sessions, il peut lire les données de session actives des utilisateurs et admins connectés.
Exploitation
Accès direct à la table sessions → lecture des données de toutes les sessions actives.
Correction recommandée
Passer SESSION_ENCRYPT=true dans le .env de production.

Moyenne

2 failles
S6 — Credentials Mailtrap exposés dans .env Moyenne
Fichier concerné
.env (MAIL_USERNAME, MAIL_PASSWORD)
Description
Les credentials Mailtrap réels (bf6eeb3334aef9 / 30ded60b400bad) sont présents. Si le .env est exposé, un attaquant peut lire tous les emails de test capturés (dont les liens de réinitialisation de mot de passe).
Correction recommandée
Utiliser des credentials différents par développeur, ne pas partager les mêmes credentials dans le .env commun.
S7 — Route de contact sans throttle Moyenne
Fichier concerné
routes/web.php (route contact.post)
Description
La route POST du formulaire de contact n'a aucun middleware throttle, contrairement au login (throttle:10,1) ou au register. Un attaquant peut envoyer des milliers de messages automatiquement.
Correction recommandée
Ajouter ->middleware('throttle:5,1') sur la route contact.post.

Faible

1 faille
S8 — Fichiers de debug HomeController1.php / RegistrationsController1.php présents Faible
Fichier concerné
app/Http/Controllers/HomeController1.php, Admin/RegistrationsController1.php
Description
Des fichiers de contrôleurs suffixés "1" (copies de travail) sont présents dans le codebase et peuvent contenir du code déprécié non maintenu.
Correction recommandée
Supprimer tous les fichiers de backup/doublon avant déploiement.

Points positifs

Bonne pratiqueDétail
Signature Stripe webhook vérifiéeStripeWebhookController utilise Webhook::constructEvent() pour valider les signatures.
Throttle sur routes sensiblesLogin (10/min), register (10/min), reset password (5/min), Stripe checkout (10/min).
Rate limiting sur le 2FAAdminLoginController limite à 5 tentatives 2FA par IP et par admin ID.
CSRF protégé correctementSeul /stripe/webhook est exclu du CSRF — pratique standard.
2FA admin implémentéAuthentification à double facteur disponible pour les comptes admin (TOTP via Fortify).
Téléchargement fichiers avec contrôle d'accèsdownloadSessionFile() vérifie inscription confirmée avant de servir le fichier.
Idempotence des paiements StripeDouble traitement webhook + page success sans doublon d'e-mail ou de confirmation.
Upload images TinyMCE validéTypes MIME whitelistés (jpeg, png, jpg, gif, svg, webp), taille max 2MB.
Permissions admin avec SpatieSystème de rôles et permissions avec middleware CheckAdminModulePermission.
Bcrypt rounds=12Niveau de sécurité correct pour le hachage des mots de passe.
Vérification email membreRoute de vérification d'email signée (middleware signed).

Rapport généré le 2 mai 2026 · Audit basé sur analyse statique du code source · Une analyse dynamique (tests de pénétration, composer audit pour les dépendances) est recommandée en complément avant mise en production.