Zurück zum Blog
27. Oktober 2025Sergei Solod5 Min. Lesezeit

Meine statische Next.js-Seite bekommt täglich Tausende Schwachstellen-Scans. Nginx merkt davon kaum etwas

In meinen Logs tauchen ständig Probes nach WordPress, PHP-Backdoors, .env und .git/config auf. Auf meiner statischen Next.js-Nginx-Seite enden sie meist als günstige Misses und 404-Antworten; die CPU-Last blieb unverändert. Entscheidend ist, was das über statische Sicherheit wirklich aussagt – und was nicht.

SicherheitNext.jsNginxDevOpsStatisches HostingAngriffsfläche

Jeden Tag landen Tausende automatisierte Schwachstellen-Scans in meinen Server-Logs. Die Requests sehen dramatisch aus:

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

Überrascht hat mich nicht die Menge, sondern die Reaktion des Servers. Während ich diesen Traffic beobachtete, bewegte sich die CPU-Last sichtbar nicht.

Diese Beobachtung stimmt. Meine frühere Erklärung war allerdings zu absolut. Statische Auslieferung ist kein magischer Schutzschild, und auch ein 404 kostet Ressourcen. Der tatsächliche Vorteil meiner Architektur ist präziser: Viele opportunistische Probes sind billig, weil dahinter fast keine serverseitige Anwendungslogik liegt, die sie erreichen könnten.

Das sind Probes, kein Beweis für einen erfolgreichen Angriff

Bei Pfaden wie /wp-admin/wp.php oder /111.php liegt es nahe, jeden Request als „Exploit“ zu bezeichnen. Technisch ist das zu ungenau. Meist sehe ich automatisiertes Probing: Bots testen bekannte Dateinamen und Endpoints und schauen, was antwortet.

Einige Pfade zielen klar auf WordPress oder PHP. Andere, etwa /.git/config und /api/.env, suchen nach versehentlich veröffentlichten Konfigurationen oder Geheimnissen. /admin ist sogar völlig generisch und kann auf manchen Websites eine legitime Route sein. Ein verdächtiger Request zeigt, wonach der Scanner sucht; er beweist nicht, dass die Schwachstelle existiert.

In meinem Fall ist die Architektur entscheidend: Die öffentliche Website besteht aus vorgerendertem statischem HTML, das mit Next.js erzeugt und direkt von Nginx ausgeliefert wird.

Warum dieser Traffic auf meinem Stack so billig ist

Für die hier betrachteten Seiten gibt es keinen PHP-Runtime und keine Datenbank hinter jedem Request. Nginx liefert vorhandene Dateien aus. Fragt ein Scanner /111.php an und diese Datei existiert nicht, startet keine PHP-Anwendung, es läuft kein WordPress-Code und es gibt keine Datenbankabfrage. Der Request endet schlicht als Miss und 404.

Damit ändert sich das Kostenmodell. In einer dynamischen Anwendung kann ein Request Routing, Framework-Code, Authentifizierung, Rendering, Datenbankzugriffe oder externe Services auslösen. Mein statischer Pfad hat wesentlich weniger bewegliche Teile. Natürlich muss Nginx trotzdem die Verbindung annehmen, HTTP verarbeiten, die Ressource suchen, loggen und antworten. Die eigentliche Anwendungsarbeit bleibt aber klein.

Ich nutze außerdem aggressives Caching, was bei normaler statischer Auslieferung hilft. Ich würde allerdings nicht jeden zufälligen 404 dem Cache zuschreiben. Ein neuer, unsinniger URI kann weiterhin die normale Nginx-Verarbeitung und einen Dateisystem-Lookup durchlaufen, bevor 404 zurückgegeben wird.

Die wichtige Korrektur: Statisch bedeutet nicht „per Definition sicher“

Diesen Teil würde ich heute deutlich vorsichtiger formulieren. Eine statische Architektur entfernt viele serverseitige Komponenten aus dem öffentlichen Request-Pfad, aber sie ersetzt keine Sicherheitsarbeit.

  • Eine exponierte Datei bleibt exponiert. Liegen .git, .env, Backups oder andere Geheimnisse versehentlich im öffentlichen Verzeichnis, kann Nginx sie genauso effizient ausliefern wie HTML, sofern die Konfiguration das nicht verhindert.
  • Nginx, TLS, Betriebssystem und Netzwerk bleiben Teil der Angriffsfläche. Sie müssen weiterhin gepatcht und sinnvoll konfiguriert werden.
  • Client-Code kann weiterhin verwundbar sein. Statisches HTML macht JavaScript, browserseitige Authentifizierungslogik oder Third-Party-Skripte nicht automatisch sicher.
  • Ressourcen lassen sich trotzdem erschöpfen. Verbindungen, Bandbreite, TLS-Handshakes, Worker, Log-I/O und Speicherplatz sind endlich. Genug Traffic kann auch einer statischen Site schaden.

Der richtige Schluss lautet deshalb nicht „diese Requests sind egal“, sondern: Viele anwendungsspezifische Probes finden in dieser Architektur schlicht nichts, was sie ausführen könnten.

„Tausende Scans pro Tag“ können gefährlicher klingen, als sie sind

Logs verstärken den Eindruck von Angriffen, weil jeder fehlgeschlagene Probe einzeln sichtbar wird. Eine Tageszahl allein sagt aber wenig über die operative Relevanz aus. Einige Tausend Requests über 24 Stunden verteilt sind etwas völlig anderes als dieselbe Zahl in einem kurzen Burst.

CPU ist ebenfalls nur ein Signal. In meinem Fall blieb sie unverändert; das ist brauchbare Evidenz dafür, dass dieser Traffic zu diesem Zeitpunkt keinen spürbaren Compute-Druck erzeugte. Es beweist aber nicht, dass es anderswo keinerlei Kosten gab. Für eine saubere Bewertung würde ich zusätzlich Request-Rate, Bandbreite, aktive Verbindungen, Nginx-Worker, Latenz, Log-Volumen und Plattennutzung betrachten.

Was ich aus diesem Hintergrundrauschen gelernt habe

Die wichtigste Erkenntnis ist für mich, dass Architektur ganze Kategorien automatisierter Angriffe irrelevant machen kann, ohne für jede Scanner-Signatur eine eigene Regel zu schreiben. Ein Bot kann den ganzen Tag nach WordPress- und PHP-Backdoors suchen; wenn der öffentliche Request-Pfad weder WordPress noch PHP enthält, haben genau diese Probes kaum Ansatzpunkte.

Ich verwechsle „für meinen Stack irrelevant“ aber nicht mehr mit „harmloser Traffic“. Mein heutiger Check sieht so aus:

  • Wissen, welche Runtimes und Services aus dem öffentlichen Request-Pfad tatsächlich erreichbar sind.
  • Secrets, Repository-Metadaten, Backups und Build-Artefakte außerhalb des Web Roots halten oder explizit blockieren.
  • Wiederholte 404-Probes als normales Internet-Hintergrundrauschen behandeln, solange keine anderen Hinweise auf gezieltes Vorgehen oder Auswirkungen vorliegen.
  • Nicht nur auf CPU schauen, bevor man missbräuchlichen Traffic für „kostenlos“ erklärt.
  • Nginx, OS, TLS-Bibliotheken und Dependencies auch bei einer statischen Anwendung aktuell halten.

Was diese Erfahrung nicht beweist

Ich habe keinen kontrollierten Benchmark durchgeführt und keinen DDoS simuliert. Ich habe lediglich Produktionslogs und Serverlast beobachtet, während täglich Tausende Scanner-Requests ankamen. Das reicht für eine praktische Aussage über mein Setup, nicht für die universelle Regel „statisch gewinnt immer“.

Was ich zuverlässig sagen kann, ist enger gefasst: Bei meinem von Nginx ausgelieferten Next.js Static Export liefen die beobachteten Scanner-Requests überwiegend auf günstige File-Misses und 404s hinaus, statt einen PHP-Runtime oder eine datenbankgestützte Anwendung zu erreichen. Die CPU-Last blieb während meiner Beobachtung unverändert.

Genau darin liegt für mich der Resilienzvorteil. Weniger bewegliche Teile machen ein System nicht unverwundbar. Sie geben zufälligem Internetrauschen lediglich weniger Möglichkeiten, zu echter Anwendungsarbeit zu werden.