Retour au blog
27 octobre 2025Sergei Solod6 min de lecture

Mon site Next.js statique reçoit des milliers de scans de vulnérabilités par jour. Nginx les remarque à peine

Mes logs sont remplis de sondes visant WordPress, des backdoors PHP, .env et .git/config. Sur mon site statique Next.js + Nginx, elles finissent surtout en miss et en 404 peu coûteuses, tandis que la charge CPU est restée stable. Voici ce que cela dit réellement de la sécurité statique — et ce que cela ne prouve pas.

SécuritéNext.jsNginxDevOpsHébergement statiqueSurface d’attaque

Chaque jour, les logs de mon serveur enregistrent des milliers de scans automatisés de vulnérabilités. Les requêtes paraissent inquiétantes :

  • /wp-admin/wp.php
  • /111.php
  • /code.php
  • /.git/config
  • /i.php
  • /admin
  • /api/.env
  • /kal.php

Ce qui m’a surpris n’était pas leur nombre, mais la réaction du serveur. Pendant que j’observais ce trafic, la charge CPU ne bougeait pas de façon visible.

Cette observation est réelle, mais mon explication initiale était trop catégorique. La diffusion statique n’est pas un bouclier magique, et une 404 n’est pas gratuite. Le vrai avantage de mon architecture est plus précis : beaucoup de sondes opportunistes coûtent peu, parce qu’elles n’ont presque aucune logique applicative côté serveur à atteindre.

Ce sont des sondes, pas la preuve d’une compromission

En voyant /wp-admin/wp.php ou /111.php, on peut être tenté d’appeler chaque requête un « exploit ». Techniquement, c’est imprécis. Ce que je vois surtout, c’est du probing automatisé : des bots essaient des noms de fichiers et des endpoints courants pour voir ce qui répond.

Certains chemins ciblent clairement WordPress ou PHP. D’autres, comme /.git/config et /api/.env, cherchent une configuration ou des secrets publiés par erreur. /admin est encore plus générique et peut être une route parfaitement légitime. Une requête suspecte m’indique ce que cherche le scanner, pas que la vulnérabilité existe.

Dans mon cas, le point décisif est l’architecture : le site public est du HTML statique pré-rendu par Next.js et servi directement par Nginx.

Pourquoi ce trafic coûte peu sur ma stack

Pour les pages dont je parle, il n’y a ni runtime PHP ni base de données derrière chaque requête. Nginx sert des fichiers déjà présents. Si un scanner demande /111.php et que le fichier n’existe pas, aucune application PHP ne démarre, aucun code WordPress ne s’exécute et aucune requête SQL n’est lancée. La requête se termine simplement par un miss et une 404.

Le modèle de coût est donc différent. Dans une application dynamique, une requête peut déclencher routing, framework, authentification, rendu, accès base de données ou appels à d’autres services. Mon chemin statique comporte beaucoup moins d’éléments. Nginx doit toujours accepter la connexion, traiter HTTP, chercher la ressource, écrire le log et répondre, mais le travail applicatif reste réduit.

J’utilise aussi un caching agressif pour le site, ce qui aide la diffusion statique normale. Je n’attribuerais toutefois pas chaque 404 aléatoire au cache : une URI inconnue peut encore suivre le traitement Nginx normal et provoquer une recherche sur le système de fichiers avant le 404.

Correction importante : statique ne veut pas dire « sécurisé par définition »

C’est le point que je formulerais différemment aujourd’hui. Une architecture statique retire beaucoup de composants serveur du chemin public, mais elle ne supprime pas le travail de sécurité.

  • Un fichier exposé reste exposé. Si .git, un fichier .env, une sauvegarde ou un secret se retrouve dans le répertoire public, Nginx peut le servir aussi efficacement qu’un fichier HTML si la configuration ne l’interdit pas.
  • Nginx, TLS, le système d’exploitation et le réseau restent dans la surface d’attaque. Ils doivent toujours être corrigés et configurés correctement.
  • Le code client peut toujours contenir des vulnérabilités. Du HTML statique ne rend pas automatiquement sûrs JavaScript, la logique d’authentification côté navigateur ou les scripts tiers.
  • L’épuisement de ressources reste possible. Connexions, bande passante, handshakes TLS, workers, I/O des logs et espace disque sont limités. Un volume suffisant peut aussi dégrader un site statique.

La conclusion correcte n’est donc pas « ces requêtes n’ont aucune importance », mais plutôt : beaucoup de sondes spécifiques à une application n’ont simplement rien à exécuter dans cette architecture.

« Des milliers de scans par jour » peut paraître plus grave que la charge réelle

Les logs rendent le bruit de fond d’Internet très visible : chaque tentative ratée devient une ligne. Mais un total quotidien ne suffit pas à mesurer l’impact opérationnel. Quelques milliers de requêtes réparties sur 24 heures ne sont pas équivalentes au même volume concentré dans un court burst.

Le CPU n’est lui aussi qu’un indicateur. Dans mon cas, il est resté stable, ce qui montre utilement que ce trafic ne créait pas de pression de calcul perceptible au moment de l’observation. Cela ne prouve pas que le coût était nul ailleurs. Pour évaluer correctement l’impact, je regarderais aussi le taux de requêtes, la bande passante, les connexions actives, les workers Nginx, la latence, le volume de logs et l’usage disque.

Ce que j’ai appris en regardant ce bruit

La leçon principale est qu’une architecture peut rendre certaines catégories d’attaques automatisées peu pertinentes sans écrire une règle pour chaque signature de scanner. Un bot peut chercher des backdoors WordPress et PHP toute la journée ; si le chemin public n’utilise ni WordPress ni PHP, ces sondes ont peu de prise.

Je ne confonds cependant plus « peu pertinent pour ma stack » avec « trafic inoffensif ». Ma règle actuelle est simple :

  • Savoir quels runtimes et services sont réellement accessibles depuis le chemin public.
  • Garder secrets, métadonnées du dépôt, sauvegardes et artefacts de build hors du web root ou les bloquer explicitement.
  • Traiter les sondes 404 répétées comme du bruit Internet normal tant qu’aucun autre élément n’indique un ciblage ou un impact.
  • Ne pas regarder uniquement le CPU avant de conclure qu’un trafic abusif ne coûte rien.
  • Maintenir Nginx, l’OS, les bibliothèques TLS et les dépendances à jour même pour une application statique.

Ce que cette expérience ne prouve pas

Je n’ai pas réalisé de benchmark contrôlé et je n’ai pas simulé de DDoS. J’ai observé les logs de production et la charge du serveur pendant que des milliers de requêtes de scanners arrivaient chaque jour. C’est suffisant pour une conclusion pratique sur mon installation, pas pour affirmer que « le statique gagne toujours ».

Ce que je peux confirmer est plus précis : sur mon export statique Next.js servi par Nginx, le trafic de scanners observé se résumait surtout à des file misses et des 404 peu coûteuses, au lieu d’atteindre un runtime PHP ou une application adossée à une base de données. La charge CPU est restée inchangée pendant mon observation.

C’est ce gain de résilience qui m’intéresse. Moins de composants ne rend pas un système invulnérable. Cela laisse simplement au bruit aléatoire d’Internet moins d’endroits où se transformer en vrai travail applicatif.