Website-Sicherheit: Best Practices Schicht für Schicht (2026)

Kernaussage

Website-Sicherheit nach Best Practices funktioniert in Schichten: Sichern Sie Domain und DNS ab (Registrar Lock, DNSSEC, CAA), erzwingen Sie modernes TLS mit HSTS, senden Sie einen strikten Satz an HTTP-Sicherheitsheadern, hashen Sie Passwörter mit Argon2id und schützen Sie Logins mit MFA und Rate Limiting, validieren Sie Eingaben und setzen Sie die Zugriffskontrolle auf dem Server durch, pinnen und prüfen Sie Abhängigkeiten, schließen Sie jeden Port, den Sie nicht bedienen, und protokollieren Sie genug, um einen Einbruch zu bemerken. Zu jeder Maßnahme unten finden Sie die genaue Konfiguration und einen kostenlosen Weg, um zu prüfen, ob sie wirklich greift – denn eine Schutzmaßnahme, die Sie nie getestet haben, ist eine, die Sie nicht haben.

Jetzt prüfen

Website-Sicherheit Best Practices als sechs Schichten: Domain und DNS, TLS, HTTP-Header, Anwendung, Abhängigkeiten, Server
Website-Sicherheit Best Practices als sechs Schichten: Domain und DNS, TLS, HTTP-Header, Anwendung, Abhängigkeiten, Server
Jetzt lesen
  1. Website-Sicherheit: Was Best Practices wirklich bedeuten
  2. Der Web-Security-Stack: Sechs Schichten, die Sie schützen müssen
  3. Schicht 1: Domain und DNS absichern
  4. Schicht 2: HTTPS und TLS richtig umsetzen
  5. Schicht 3: HTTP-Sicherheitsheader
  6. Schicht 4: Authentifizierung, die Credential Stuffing standhält
  7. Sessions, Cookies und CSRF
  8. Eingaben validieren, Ausgaben kodieren
  9. Broken Access Control: Das Risiko Nummer eins
  10. Schicht 5: Abhängigkeiten und Software-Lieferkette
  11. Schicht 6: Server-Härtung: Ports, Patches, Secrets und Backups
  12. E-Mail-Authentifizierung: SPF, DKIM und DMARC
  13. Protokollieren, überwachen und für den Ernstfall planen
  14. Testen: Scanner, Penetrationstests und laufende Prüfungen
  15. Die Checkliste für Website-Sicherheit
  16. So passt das zu den OWASP Top 10:2025
  17. Häufige Fragen zur Website-Sicherheit

Website-Sicherheit: Was Best Practices wirklich bedeuten

Website-Sicherheit nach Best Practices umfasst alle Maßnahmen, die verhindern, dass eine Website oder Webanwendung übernommen, verunstaltet, als Angriffswerkzeug gegen die eigenen Besucher missbraucht oder unbemerkt ihrer Daten beraubt wird. Das ist weder ein einzelnes Produkt noch eine einzelne Einstellung, sondern ein Stapel von Entscheidungen: Er beginnt beim Domain-Registrar und reicht über DNS, TLS, die HTTP-Header Ihres Servers, den Code für Logins und Eingaben, die Drittanbieter-Pakete, auf denen Sie aufbauen, und den Server selbst bis zu den Logs, die Ihnen zeigen, dass etwas schiefgelaufen ist.

Der Grund, in Schichten zu denken: Angreifer tun es auch. Der 2026 Data Breach Investigations Report von Verizon, der mehr als 22.000 Sicherheitsvorfälle von November 2024 bis Oktober 2025 auswertet, stellte fest: 31 % der Einbrüche begannen mit einer ausgenutzten Software-Schwachstelle – nach 20 % im Vorjahr und erstmals vor gestohlenen Zugangsdaten (13 %); Phishing blieb stabil bei 16 %. Ransomware kam bei 48 % der Vorfälle vor, nach 44 %. Ein einziger fehlender Patch, ein durchgesickerter API-Schlüssel oder eine Admin-Seite ohne Rate Limiting genügt. Keine der Maßnahmen in diesem Leitfaden ist exotisch; gehackt werden meist die Websites, die auf einer Schicht die Grundlagen ausgelassen haben, während sie eine andere perfektionierten.

Dieser Leitfaden ist von außen nach innen aufgebaut. Jede Maßnahme sagt Ihnen, warum sie wichtig ist, was genau zu konfigurieren ist und wie Sie sie prüfen – mit einem Befehl oder einem kostenlosen Tool wie dem HTTP-Header-Checker oder dem SSL-Checker. Denn eine Einstellung, die Sie für aktiv halten, aber nie geprüft haben, schützt nichts.

Check a site's security headers

Der Web-Security-Stack: Sechs Schichten, die Sie schützen müssen

Jeder Angriff auf eine Website trifft eine von sechs Schichten. Die folgende Tabelle ist die Landkarte für den Rest dieses Leitfadens: was auf jeder Schicht liegt, wie sie typischerweise angegriffen wird und mit welchem kostenlosen Test Sie bestätigen, dass Ihre Abwehr tatsächlich greift.

SchichtWas Angreifer hier tunZentrale MaßnahmenPrüfen mit
1. Domain und DNSDomain kapern, Nameserver ändern, verwaiste Subdomains übernehmen, gefälschte Zertifikate ausstellen lassenRegistrar Lock, MFA, DNSSEC, CAA, Prüfung veralteter EinträgeWHOIS-Abfrage, DNS-Health-Check, Subdomain-Finder
2. Transport (TLS)Herabstufung auf HTTP, Verschlüsselung aushebeln, alte Cipher ausnutzen, abgelaufene ZertifikateTLS 1.2+, HSTS (Preload optional), automatisierte ErneuerungSSL-Checker
3. HTTP-HeaderSkripte einschleusen (XSS), die Seite für Clickjacking in Frames einbetten, Content-Types erraten lassen, Referrer preisgebenCSP, frame-ancestors, nosniff, Referrer-Policy, Permissions-PolicyHTTP-Header-Checker
4. AnwendungCredential Stuffing, Injection, fehlerhafte Zugriffskontrolle, CSRF, unsichere UploadsArgon2id + MFA + Rate Limits, parametrisierte Abfragen, serverseitige Autorisierung, SameSite-CookiesCode-Review, ZAP, Passwort-Stärke-Test
5. AbhängigkeitenVergiftete Pakete, bekannte CVEs in Bibliotheken, kompromittierte CI-PipelinesLockfiles, Audits, gepinnte Versionen, SBOM, Tokens mit minimalen Rechtennpm audit, Dependabot, Trivy
6. Server und BetriebOffene Ports, Standard-Zugangsdaten, fehlende Patches, keine Backups, keine LogsFirewall, SSH nur mit Schlüssel, Patching, 3-2-1-Backups, zentrales LoggingPort-Checker, IP-Blacklist-Checker

Arbeiten Sie von oben nach unten. Die Schichten 1 bis 3 sind Konfiguration, die Sie an einem Nachmittag erledigen können, und sie schützen jede Seite auf einmal. Die Schichten 4 bis 6 sind dauerhafte Gewohnheiten, die in Ihrem Code-Review- und Deployment-Prozess verankert sein müssen.

Schicht 1: Domain und DNS absichern

Alles Weitere in diesem Leitfaden setzt voraus, dass Sie Ihre Domain noch kontrollieren. Kann sich ein Angreifer bei Ihrem Registrar anmelden oder Ihre Nameserver ändern, leitet er Ihren Traffic beliebig um, erhält ein gültiges Zertifikat für Ihren Namen und liest jede E-Mail an Sie mit – ohne dass Ihr Anwendungscode jemals ausgeführt wird. Die Sicherheit von Domain und DNS ist deshalb die erste Best Practice der Websicherheit, und sie besteht fast ausschließlich aus Konfiguration.

Beginnen Sie mit einer WHOIS-Abfrage Ihrer eigenen Domain und prüfen Sie drei Dinge: Die Statuscodes enthalten clientTransferProhibited, das Ablaufdatum liegt mehr als ein Jahr in der Zukunft, und der Registrar ist einer, bei dem Sie tatsächlich ein Konto haben. Erstaunlich oft liegt die Domain eines Unternehmens noch im Registrar-Konto eines ehemaligen Dienstleisters. Unser Leitfaden zur WHOIS-Abfrage erklärt jeden Statuscode, der Ihnen begegnen kann.

Registrar Lock, MFA und Ablaufwarnungen

Aktivieren Sie den Registrar Lock (auch Transfer-Sperre genannt), damit die Domain nicht zu einem anderen Registrar umgezogen werden kann, ohne dass Sie sie ausdrücklich entsperren, und schalten Sie Multi-Faktor-Authentifizierung für das Registrar-Konto selbst ein. Registrar-Konten sind ein beliebtes Phishing-Ziel, gerade weil ein einziger Login alles Nachgelagerte kontrolliert. Nutzen Sie einen Hardware-Schlüssel oder eine Authenticator-App statt SMS, wo immer der Registrar das zulässt.

Stellen Sie die Domain auf automatische Verlängerung mit einer Zahlungsmethode, die nicht abläuft, und legen Sie sich trotzdem 60 Tage vor dem Ablaufdatum einen Kalendereintrag an. Eine abgelaufene Domain ist nicht am Tag des Ablaufs verloren, aber sobald Karenz- und Einlösefrist verstrichen sind (bei .com bis zu etwa 80 Tage), wird sie gelöscht, und Drop-Catch-Dienste registrieren sie binnen Sekunden nach der Freigabe. Der Käufer erbt Ihre E-Mails, Ihren Traffic und alle OAuth-Logins, die Ihrer Domain vertrauen.

  • Registry Lock (eine manuelle Sperre auf Registry-Ebene, die außerhalb des normalen Kontos gesetzt wird) ist für eine geschäftskritische Domain die Zusatzgebühr wert: Selbst ein kompromittiertes Registrar-Konto kann dann die Nameserver nicht mehr ändern.
  • Trennen Sie die Rollen. Wer die Domain bezahlt, welches Konto sie besitzt und wer der DNS-Anbieter ist, sollte jeweils dokumentiert sein und nicht am Postfach eines einzelnen Mitarbeiters hängen.
  • Aktivieren Sie WHOIS-Privacy, damit Ihre Kontaktdaten keine Vorlage für Phishing liefern, und hinterlegen Sie im Konto eine überwachte Rollenadresse wie domains@.

Die Zone mit DNSSEC signieren

DNSSEC signiert Ihre DNS-Zone, damit ein Resolver gefälschte Antworten erkennen kann. Ohne DNSSEC kann ein Angreifer, der den Cache eines Resolvers vergiften kann, Ihre Besucher auf einen gefälschten Server schicken, während der Browser weiterhin Ihren Domainnamen anzeigt. Die meisten verwalteten DNS-Anbieter (Cloudflare, Route 53, Google Cloud DNS und viele Registrare) aktivieren es mit einem Schalter; der einzige manuelle Schritt ist die Veröffentlichung des DS-Eintrags beim Registrar. Prüfen Sie es mit dig oder mit dem DNS-Health-Check, der den DS-Eintrag und die Signaturen kontrolliert:

bash
dig +dnssec +short yourdomain.com A
# A signed zone returns the record AND an RRSIG line:
# 203.0.113.10
# A 13 2 3600 20270115000000 20261225000000 34505 yourdomain.com. Kx3f...==

dig +short yourdomain.com DS
# A DS record at the parent zone proves the chain of trust is complete
# 2371 13 2 6A1B...C9

Zertifikatsausstellung mit CAA einschränken

Ein CAA-Eintrag (RFC 8659) legt fest, welche Zertifizierungsstellen Zertifikate für Ihre Domain ausstellen dürfen. Jede öffentliche CA muss ihn vor der Ausstellung prüfen – ein CAA-Eintrag sperrt also einen Angreifer aus, der die Domain-Validierung einer anderen CA ausgetrickst hat. Drei Einträge decken die üblichen Fälle ab: wer ausstellen darf, wer Wildcards ausstellen darf und wohin abgelehnte Anfragen gemeldet werden:

dns
yourdomain.com.  CAA 0 issue "letsencrypt.org"
yourdomain.com.  CAA 0 issuewild ";"
yourdomain.com.  CAA 0 iodef "mailto:security@yourdomain.com"

Veraltete Einträge prüfen: Subdomain Takeover

Ein Subdomain Takeover entsteht, wenn ein DNS-Eintrag noch auf einen Dienst zeigt, den Sie nicht mehr nutzen: ein CNAME auf eine gelöschte GitHub-Pages-Seite, eine Azure-App, einen S3-Bucket oder den Hostnamen eines SaaS-Anbieters. Jeder kann das verwaiste Ziel registrieren und dann unter old-app.yourdomain.com in Ihrem Namen Inhalte ausliefern – samt gültigem Zertifikat. Es ist ein regelmäßiger Fund in Bug-Bounty-Programmen, weil sich niemand an den Eintrag erinnert.

Lassen Sie Ihre Domain durch den Subdomain-Finder laufen: Er durchsucht zwei Certificate-Transparency-Log-Dienste, Cert Spotter (aktuelle Zertifikate) und crt.sh (jedes Zertifikat seit 2013), probiert 1.000 gängige Namen, löst jeden Namen live auf, markiert hängende CNAMEs und zeigt, welcher Host oder CDN dahintersteckt. Löschen Sie jeden Eintrag, dessen Ziel NXDOMAIN oder die „No such app“-Seite eines Anbieters liefert; ein DNS-Lookup bestätigt einen einzelnen Namen. Wiederholen Sie das vierteljährlich und machen Sie das Löschen des DNS-Eintrags zum Teil jeder Stilllegung eines Dienstes.

Certificate Transparency ist zugleich Ihr Frühwarnsystem: Cert Spotter und das CT-Monitoring von Cloudflare können Sie per E-Mail benachrichtigen, sobald irgendeine CA ein Zertifikat für Ihre Domain ausstellt. Ein unerwartetes Zertifikat ist oft das erste sichtbare Anzeichen dafür, dass DNS oder Registrar kompromittiert wurden.

Schicht 2: HTTPS und TLS richtig umsetzen

HTTPS ist keine Best Practice mehr, sondern die Grundlage, und Browser kennzeichnen reine HTTP-Seiten als „Nicht sicher“. Google hat zudem angekündigt, dass der Browser ab Chrome 154 (Oktober 2026) nachfragt, bevor er eine öffentliche Website über reines HTTP öffnet (Google). Was eine sichere Website noch von einer bloß verschlüsselten trennt, sind die akzeptierten TLS-Versionen, die Frage, ob man Sie überhaupt noch über HTTP erreichen kann, und ob die Erneuerung so gut automatisiert ist, dass sie die seit März 2026 greifenden Kürzungen der Zertifikatslaufzeiten übersteht.

Mindestens TLS 1.2, bevorzugt TLS 1.3

TLS 1.0 und 1.1 wurden 2021 mit RFC 8996 offiziell für veraltet erklärt, und kein aktueller Browser handelt sie noch aus. Deaktivieren Sie sie auf dem Server, bevorzugen Sie TLS 1.3 (das jeden als schwach bekannten Cipher streicht und den Handshake in einem einzigen Roundtrip abschließt) und behalten Sie TLS 1.2 nur mit AEAD-Cipher-Suites wie ECDHE-ECDSA-AES128-GCM-SHA256 oder ECDHE-RSA-CHACHA20-POLY1305 bei.

Zwei Zeilen zählen, wenn Sie von außen testen: das ausgehandelte Protokoll und Verify return code: 0, das bedeutet, dass die gesamte Zertifikatskette validiert wurde. Ein fehlendes Zwischenzertifikat ist eine häufige Ursache für Meldungen wie „funktioniert in Chrome, scheitert in curl und auf Android“; unser Leitfaden zur SSL-Zertifikatskette zeigt die Lösung, und der SSL-Checker meldet eine unvollständige Kette direkt. Hier die Prüfung gegen dnsrobot.net am 27. Oktober 2026, danach ein Test, ob der Server TLS 1.1 ablehnt:

bash
echo | openssl s_client -connect dnsrobot.net:443 -servername dnsrobot.net 2>/dev/null \
  | grep -E 'Protocol|Cipher|Verify return'

# New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
# Protocol: TLSv1.3
# Verify return code: 0 (ok)

# Is TLS 1.1 refused? SECLEVEL=0 lets OpenSSL 3 and later offer it at all
openssl s_client -connect example.com:443 -servername example.com -tls1_1 \
  -cipher 'DEFAULT:@SECLEVEL=0' </dev/null 2>&1 | grep -E 'alert|Cipher is'

# Refused, as it should be:  ...tlsv1 alert protocol version...
#                            New, (NONE), Cipher is (NONE)
# Still accepted (fix it):   New, TLSv1.0, Cipher is ECDHE-ECDSA-AES128-SHA
#   (TLSv1.0 is the cipher's version; the handshake was TLS 1.1)

In Cipher-Listen veralten kopierte Konfigurationen am schnellsten. Statt sie von Hand zu schreiben, erzeugen Sie den aktuell empfohlenen Server-Block für nginx, Apache, Caddy oder HAProxy mit dem Mozilla SSL Configuration Generator und wählen das Profil „Intermediate“, sofern Sie nicht sehr alte Clients unterstützen müssen.

HSTS: Nie wieder HTTP im Browser

Eine Weiterleitung von HTTP auf HTTPS allein reicht nicht. Die allererste Anfrage eines Besuchers an http://yourdomain.com geht weiterhin im Klartext über die Leitung, und ein Angreifer im selben Netzwerk kann sie beantworten, bevor Ihre Weiterleitung greift. HTTP Strict Transport Security (RFC 6797) behebt das: Sobald ein Browser den Header einmal gesehen hat, schreibt er jede künftige http://-URL Ihrer Domain in https:// um, bevor er überhaupt etwas sendet.

Verwenden Sie ein max-age von mindestens einem Jahr (31536000 Sekunden) und ergänzen Sie includeSubDomains, sobald jede Subdomain HTTPS ausliefert. Das Preloading auf hstspreload.org, das die Domain fest in Chrome, Firefox, Safari und Edge einbaut, ist optional: Die Betreiber der Liste selbst sagen inzwischen, HSTS werde empfohlen, Preloading aber nicht, weil Chrome und Safari Navigationen ohnehin auf HTTPS hochstufen und das Verlassen der Liste Monate dauert. Prüfen Sie den Header mit dem HTTP-Header-Checker, der HSTS mit den Tests des Mozilla HTTP Observatory bewertet.

http
Strict-Transport-Security: max-age=31536000; includeSubDomains

47-Tage-Zertifikate: Automatisieren Sie die Erneuerung jetzt

Das CA/Browser Forum verkürzt mit dem Ballot SC-081 die maximale Laufzeit jedes öffentlichen TLS-Zertifikats schrittweise. Die erste Stufe trat am 15. März 2026 in Kraft: Jedes Zertifikat, das Sie heute kaufen oder erneuern, ist bereits auf 200 Tage begrenzt, und ab 2029 muss ein Zertifikat etwa alle sechs Wochen ersetzt werden:

StichtagMaximale ZertifikatslaufzeitWiederverwendung der Domain-Validierung
Vor dem 15. März 2026398 Tage398 Tage
15. März 2026200 Tage200 Tage
15. März 2027100 Tage100 Tage
15. März 202947 Tage10 Tage

Manuelle Erneuerung hält diesem Zeitplan nicht stand. Best Practice ist die vollautomatische Ausstellung über ACME: Let's Encrypt oder Google Trust Services per certbot, acme.sh oder Caddy, oder die automatischen Zertifikate von Cloudflare, Vercel, Netlify und den meisten Hosting-Panels. Testen Sie den Erneuerungsweg, bevor Sie ihn brauchen (certbot renew --dry-run bei certbot); die typische Stolperfalle ist ein seit der letzten Erneuerung hinzugefügter CAA-Eintrag oder eine neue Firewall-Regel, die nun die Validierung blockiert. Egal, was Sie einsetzen: Überwachen Sie das Ablaufdatum auch von außen – der SSL-Checker zeigt die verbleibenden Tage, und ein abgelaufenes Zertifikat verwandelt jeden Besuch in eine ganzseitige Browserwarnung.

Schicht 3: HTTP-Sicherheitsheader

Sicherheitsheader sind Anweisungen Ihres Servers an den Browser, was er mit Ihren Seiten tun darf und was nicht: welche Skripte laufen dürfen, ob die Seite eingebettet werden darf, ob der Browser Content-Types erraten darf und was er anderen Websites darüber mitteilen soll, woher ein Besucher kam. Sie kosten nichts, gelten für jede Seite auf einmal und blockieren ganze Angriffsklassen. Außerdem ist dies die Schicht, die die meisten Websites teilweise falsch machen – deshalb bewertet der HTTP-Header-Checker sie mit den Tests des Mozilla HTTP Observatory. Das hat github.com am 27. Oktober 2026 gesendet, gekürzt auf die Sicherheitsheader (sein script-src nennt einen Asset-Host und einen Skript-Hash, ohne 'unsafe-inline'):

bash
curl -sI https://github.com/ | grep -iE 'strict-transport|content-security|x-frame|x-content-type|referrer-policy'

strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
content-security-policy: default-src 'none'; base-uri 'self'; ... frame-ancestors 'none'; ... script-src github.githubassets.com 'sha256-6AKuI+cDd1MoUL1u4eqrA9PXmnPAkOB4h7421hPUUm0='; ...

Die sieben Header, die jede Website senden sollte

Das sind die Werte, die Sie bei einer typischen Website anstreben sollten. In der Bewertung des Mozilla HTTP Observatory, die unser HTTP-Header-Checker nutzt, kostet eine fehlende CSP 25 Punkte, ein fehlendes HSTS oder fehlender Framing-Schutz je 20 und ein fehlendes nosniff 5; Referrer-Policy und COOP bringen Bonuspunkte, sobald die Punktzahl noch bei 90 oder mehr liegt. Permissions-Policy wird nicht bewertet (nur Chromium-Browser lesen sie), ist aber trotzdem sinnvoll.

HeaderEmpfohlener WertWas er verhindert
Strict-Transport-Securitymax-age=31536000; includeSubDomainsProtokoll-Downgrade, Cookie-Diebstahl über HTTP
Content-Security-PolicyNonce-basiertes script-src mit 'strict-dynamic'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'Cross-Site-Scripting (XSS), Dateninjektion, Clickjacking
X-Content-Type-OptionsnosniffMIME-Sniffing, das einen Upload in ausführbares Skript verwandelt
Referrer-Policystrict-origin-when-cross-originPreisgabe vollständiger URLs (Tokens, Suchbegriffe) an Dritte
Permissions-Policycamera=(), microphone=(), geolocation=(), payment=()Drittanbieter-Skripte, die unbemerkt mächtige Browser-APIs nutzen
X-Frame-OptionsDENY (Legacy-Fallback für frame-ancestors)Clickjacking in Browsern ohne CSP Level 2
Cross-Origin-Opener-Policysame-originFensterübergreifende Angriffe über window.opener

Content Security Policy einführen, ohne die Website lahmzulegen

Eine Content Security Policy ist die wirksamste Einzelmaßnahme gegen XSS, weil sie eingeschleuste Skripte selbst dann an der Ausführung hindert, wenn eine Injection-Lücke existiert. Der Haken: Eine strikte Policy bricht jedes Inline-Skript und jedes Drittanbieter-Tag, das Sie vergessen haben. Der moderne Ansatz, von Google empfohlen und auf MDN dokumentiert, ist eine Nonce-basierte Policy: Der Server erzeugt pro Antwort eine zufällige Nonce, setzt sie in jedes Script-Tag, das er bewusst ausgibt, und der Browser verweigert alles andere.

'strict-dynamic' macht die Policy praxistauglich: Ein Skript mit Nonce darf weitere Skripte nachladen (Analytics, Tag-Manager, Widgets), ohne dass jedes einzeln freigegeben werden muss, während moderne Browser die Tokens https: und 'unsafe-inline' ignorieren – sie dienen nur als Fallback für alte Browser. Führen Sie die Policy zuerst mit Content-Security-Policy-Report-Only ein, beobachten Sie eine Woche lang die Verstoßberichte und schalten Sie dann auf Durchsetzung um. Frameworks wie Next.js, Rails und Django unterstützen Nonces von Haus aus; statische Websites können stattdessen ein Hash-basiertes script-src verwenden.

http
Content-Security-Policy:
  script-src 'nonce-r4nd0m1z3dV4lu3' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none';
  base-uri 'none';
  frame-ancestors 'none';
  form-action 'self';
  report-to csp-endpoint

<!-- Only scripts carrying the nonce run; strict-dynamic lets them load their own dependencies -->
<script nonce="r4nd0m1z3dV4lu3" src="/app.js"></script>

Eine Allowlist-Policy wie script-src 'self' https://cdn.example.com ist besser als nichts, doch jeder JSONP-Endpunkt und jede alte Bibliothek auf einem freigegebenen Host lässt sich zu ihrer Umgehung nutzen. Wenn Sie noch keine Nonces einsetzen können, setzen Sie zumindest object-src 'none' und base-uri 'none' – das schließt sofort zwei gängige Umgehungswege.

Clickjacking: frame-ancestors und X-Frame-Options

Beim Clickjacking wird Ihre Website unsichtbar in die Seite eines Angreifers geladen, und der Besucher wird dazu gebracht, auf einen Button zu klicken, den er nicht sieht. frame-ancestors 'none' in der CSP (oder 'self', wenn Sie eigene Seiten einbetten) verhindert das in allen aktuellen Browsern, X-Frame-Options: DENY deckt ältere ab. Bieten Sie bewusst ein einbettbares Widget an, nehmen Sie nur diesen Pfad aus – und nur für die Origins, die ihn brauchen. Unser Leitfaden zu X-Frame-Options zeigt die genauen Serverregeln und die „refused to connect“-Fehler, auf die Sie beim Testen stoßen werden.

nosniff, Referrer-Policy, Permissions-Policy und COOP

X-Content-Type-Options: nosniff hindert den Browser daran, einen Content-Type eigenmächtig anders zu deuten – genau das macht aus einem hochgeladenen „Bild“ mit HTML-Inhalt eine ausführbare Seite. Referrer-Policy: strict-origin-when-cross-origin (Standard in aktuellen Browsern, aber setzen Sie es explizit) sendet nur Ihren Origin an andere Websites, sodass Passwort-Reset-Tokens und Suchanfragen in URLs privat bleiben. Permissions-Policy deaktiviert Browserfunktionen, die Sie nicht nutzen, damit ein kompromittiertes Drittanbieter-Skript weder die Kamera öffnen noch den Standort auslesen kann. Cross-Origin-Opener-Policy: same-origin kappt die window.opener-Verbindung zu Seiten, die Sie öffnen, und blockiert damit eine Klasse fensterübergreifender Angriffe.

Auch Header, die Sie entfernen, zählen: Server und X-Powered-By verraten Schwachstellen-Scannern exakte Software-Versionen, und X-XSS-Protection ist veraltet und kann in alten Browsern Fehler verursachen – setzen Sie es auf 0 oder lassen Sie es weg. Der CMS-Detector zeigt, was jeder über Ihren Stack und dessen Versionen aus der Seite selbst erfahren kann.

Setzen Sie Header einmal zentral am Edge (CDN, Reverse Proxy oder Framework-Middleware) statt pro Seite. In Next.js ist das die Proxy- oder Middleware-Datei, in nginx ein add_header-Block im Server-Kontext, in Apache Header always set. Führen Sie den HTTP-Header-Checker anschließend nach jedem Deployment erneut aus, denn eine neue Framework-Version oder CDN-Einstellung kann stillschweigend einen Header verlieren.

Schicht 4: Authentifizierung, die Credential Stuffing standhält

Angreifer raten Passwörter selten einzeln. Sie spielen Milliarden von E-Mail-Passwort-Paaren ab, die bei anderen Websites geleakt wurden (Credential Stuffing), und phishen den Rest. Best Practices für die Authentifizierung haben daher drei Teile: Passwörter so speichern, dass ein Datenbank-Leak kein Passwort-Leak ist, ein gestohlenes Passwort allein nutzlos machen und Brute Force so verlangsamen, dass es keine Rolle spielt. OWASP führt Authentication Failures in den OWASP Top 10:2025 auf Platz A07.

Passwörter mit Argon2id oder bcrypt hashen

Speichern Sie niemals ein Passwort – und niemals einen schnellen Hash davon. MD5, SHA-1 und selbst SHA-256 sind auf Geschwindigkeit ausgelegt, sodass eine geleakte Tabelle solcher Hashes auf einer einzigen GPU mit Milliarden Versuchen pro Sekunde getestet werden kann. Verwenden Sie eine langsame, speicherintensive Passwort-Hashing-Funktion mit individuellem Salt pro Passwort. Das OWASP Password Storage Cheat Sheet empfiehlt in dieser Reihenfolge:

  • Argon2id mit mindestens 19 MiB Speicher, 2 Iterationen und Parallelitätsgrad 1 (oder 46 MiB mit 1 Iteration).
  • scrypt mit N = 2^17, r = 8, p = 1, wo Argon2 nicht verfügbar ist.
  • bcrypt mit einem Work Factor von 10 oder höher (beachten Sie die Eingabegrenze von 72 Byte; das Vorab-Hashen längerer Passwörter erfordert Sorgfalt).
  • PBKDF2-HMAC-SHA256 mit 600.000 Iterationen nur dort, wo FIPS-Konformität es erzwingt.
javascript
// Node.js with the argon2 package
import argon2 from "argon2";

const hash = await argon2.hash(password, {
  type: argon2.argon2id,
  memoryCost: 19456, // KiB = 19 MiB
  timeCost: 2,
  parallelism: 1,
});

// Later, on login:
const ok = await argon2.verify(hash, submittedPassword);

Stimmen Sie die Kosten so ab, dass ein Hash auf Ihrem Login-Server etwa 100 bis 250 ms dauert. Für echte Nutzer ist das unmerklich, doch es hält jeden CPU-Kern bei einer Handvoll Versuche pro Sekunde und selbst eine High-End-Grafikkarte bei Tausenden statt Milliarden. Hashen Sie bei erfolgreichem Login neu, wann immer Sie die Parameter erhöhen – so aktualisieren sich alte Hashes von selbst.

Passwortregeln, die wirklich helfen (NIST SP 800-63B)

Die Kompositionsregeln, die die meisten Websites noch erzwingen (ein Großbuchstabe, ein Sonderzeichen, Wechsel alle 90 Tage), führen zu vorhersehbaren Passwörtern wie Summer2026! und verleiten Menschen dazu, sie wiederzuverwenden. Die aktuelle Richtlinie NIST SP 800-63B ersetzt sie durch Regeln, die messen, worauf es ankommt:

  • Mindestens 8 Zeichen, wenn zusätzlich MFA verlangt wird, und mindestens 15 Zeichen für ein Passwort, das allein verwendet wird; erlauben Sie mindestens 64.
  • Keine Kompositionsregeln und kein erzwungener regelmäßiger Wechsel; verlangen Sie eine Änderung nur bei Hinweisen auf eine Kompromittierung.
  • Prüfen Sie jedes neue Passwort gegen eine Liste geleakter Passwörter (mit der Range-API von Have I Been Pwned geht das, ohne das Passwort zu übermitteln) und lehnen Sie bekannte ab.
  • Erlauben Sie Einfügen und Passwortmanager, akzeptieren Sie Leerzeichen und Unicode und geben Sie Hinweise, die bei der Wahl eines starken Passworts helfen – besonders direkt nachdem Sie eines abgelehnt haben.

Unser Password-Strength-Tester zeigt, wie sich diese Maßnahmen von den alten Regeln unterscheiden: Er schätzt, wie lange ein Passwort unter 8 benannten Angriffen zum Knacken braucht, zeigt die Muster, die es schwächen, und gleicht es mit Leak-Daten ab, ohne das Passwort zu übertragen – ein weit nützlicheres Feedback als eine rote Meldung „Sonderzeichen erforderlich“.

MFA und Passkeys

Multi-Faktor-Authentifizierung macht ein gestohlenes Passwort zur Sackgasse. Bieten Sie sie allen an und verlangen Sie sie für Admin-, Finanz- und Support-Rollen. Ordnen Sie die Optionen nach Phishing-Resistenz: Passkeys und FIDO2-Sicherheitsschlüssel lassen sich nicht phishen, weil der Schlüssel an Ihren echten Origin gebunden ist; Authenticator-Apps (TOTP) sind gut; SMS-Codes sind besser als nichts, können aber per SIM-Swapping abgefangen werden. Passkeys werden von allen aktuellen Browsern und Betriebssystemen unterstützt und ersetzen das Passwort vollständig – womit auch Credential Stuffing als Angriffskategorie wegfällt.

Schützen Sie den Wiederherstellungsweg so sorgfältig wie den Login: Wiederherstellungscodes nur gehasht speichern, E-Mail-Resets mit Einmal-Tokens, die innerhalb von 15 Minuten ablaufen, und keine Sicherheitsfragen.

Rate Limiting, Sperren und Bot-Abwehr

Begrenzen Sie Login-, Registrierungs-, Passwort-Reset- und MFA-Endpunkte pro IP und pro Konto, und antworten Sie nach Erreichen des Limits mit 429 Too Many Requests und einem Retry-After-Header (unser Leitfaden zu HTTP-Fehler 429 erklärt, wie Clients reagieren sollten). Kombinieren Sie das mit einer wachsenden Verzögerung oder einer temporären Sperre nach wiederholten Fehlversuchen bei einem Konto sowie mit einem CAPTCHA oder einer Proof-of-Work-Challenge für Endpunkte, die verteilte Angriffe abbekommen. Protokollieren Sie jeden fehlgeschlagenen Login mit Quell-IP, damit das Muster eines Credential-Stuffing-Laufs in Minuten statt in Monaten sichtbar wird.

nginx
# nginx: 5 login attempts at once, then 1 every 12 seconds, per client IP
# (limit_req sends no Retry-After header; add one on your 429 page if clients need it)
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

location = /api/login {
    limit_req zone=login burst=4 nodelay;
    limit_req_status 429;
    proxy_pass http://app;
}

Halten Sie die Fehlermeldungen für „unbekannter Benutzer“ und „falsches Passwort“ identisch, und sorgen Sie für die gleiche Antwortzeit (hashen Sie ein Dummy-Passwort, wenn der Benutzer nicht existiert). Sonst dient das Login-Formular nebenbei als API zur Benutzer-Enumeration.

Sessions, Cookies und CSRF

Nach dem Login ist das Session-Cookie der Benutzer – es verdient also denselben Schutz wie das Passwort. Drei Cookie-Attribute und ein Namenspräfix erledigen den Großteil der Arbeit:

  • Secure sorgt dafür, dass das Cookie nie über unverschlüsseltes HTTP gesendet wird und sich so nicht im öffentlichen WLAN mitschneiden lässt.
  • HttpOnly macht es für JavaScript unsichtbar, sodass eine XSS-Lücke es nicht auslesen kann.
  • SameSite=Lax (oder Strict für Admin-Panels) hält es aus Cross-Site-POST-Anfragen heraus und neutralisiert damit die meisten CSRF-Angriffe.
  • Das Präfix __Host- lässt den Browser das Cookie nur akzeptieren, wenn es Secure ist, Path=/ und kein Domain-Attribut hat – so kann eine Subdomain es nicht überschreiben.
http
Set-Cookie: __Host-session=9f1c7e2a...; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=28800

Zustandsändernde Aktionen dürfen niemals per GET erreichbar sein. Ein Link wie /account/delete?id=42 lässt sich über ein <img>-Tag auf jeder beliebigen Seite auslösen, die der Nutzer besucht – ganz gleich, wie gut Ihre Cookie-Flags sind.

CSRF: Eine zweite Verteidigungslinie hinter SameSite

Cross-Site Request Forgery (CSRF) bringt einen eingeloggten Browser dazu, von einer anderen Seite aus eine zustandsändernde Anfrage an Ihre Website zu senden. SameSite-Cookies stoppen den Normalfall, doch behalten Sie für jede Nicht-GET-Anfrage eine zweite Abwehr bei: ein Anti-CSRF-Token pro Session in einem versteckten Feld oder einem eigenen Header, oder eine Prüfung, ob der Header Origin (oder Sec-Fetch-Site) zu Ihrem eigenen Origin passt. Die meisten Frameworks (Django, Rails, Laravel, Next.js Server Actions) tun das standardmäßig; der Fehler besteht darin, es für einen API-Endpunkt abzuschalten und diesen Endpunkt dann doch aus dem Browser aufzurufen.

Session-IDs, Rotation und JWTs

Erzeugen Sie Session-IDs mit mindestens 128 Bit Zufall, rotieren Sie die ID beim Login und bei jeder Rechteänderung, um Session Fixation zu verhindern, lassen Sie Sessions nach Inaktivität ablaufen und geben Sie Nutzern einen „Überall abmelden“-Button, der die Sessions serverseitig ungültig macht. Für JWTs gilt: kurzlebig halten (Minuten, mit einem widerrufbaren Refresh-Token), niemals in localStorage speichern, wo jedes Skript sie lesen kann, und einen geleakten Signaturschlüssel als vollständigen Einbruch behandeln, denn jedes jemals damit signierte Token lässt sich nun fälschen.

Eingaben validieren, Ausgaben kodieren

Injection (A05:2025) und Cross-Site-Scripting sind derselbe Fehler an verschiedenen Stellen: Daten eines Nutzers werden an einen Interpreter (SQL, die Shell, eine LDAP-Abfrage, eine HTML-Seite) übergeben, als wären sie Code. Die Lösung ist ebenfalls überall dieselbe: Daten und Code strikt trennen und niemals einen Befehl per String-Verkettung zusammenbauen.

Parametrisierte Abfragen statt zusammengebauter Strings

Verwenden Sie für SQL Prepared Statements oder ein ORM, das sie erzeugt; die Datenbank behandelt die Eingabe dann als Wert, der die Struktur der Abfrage nie verändern kann. Dieselbe Regel gilt für Shell-Befehle (ein Argument-Array übergeben, nie einen String), für NoSQL-Filter (Operator-Objekte wie {"$gt": ""} in Nutzereingaben ablehnen) und für Dateipfade (den Pfad auflösen und prüfen, dass er im vorgesehenen Verzeichnis bleibt).

javascript
// Vulnerable: the input becomes part of the query text
const rows = await db.query(`SELECT * FROM users WHERE email = '${email}'`);

// Safe: the driver sends the value separately from the query
const rows = await db.query("SELECT * FROM users WHERE email = $1", [email]);

// Python / psycopg: same idea
cur.execute("SELECT * FROM users WHERE email = %s", (email,))

Output-Encoding stoppt XSS

Cross-Site-Scripting entsteht, wenn nutzergesteuerter Text in eine Seite geschrieben wird, ohne ihn für den jeweiligen Kontext zu kodieren. Moderne Template-Engines (React und JSX, Vue, Jinja2, Blade, ERB) kodieren standardmäßig; XSS entsteht heute meist über die Notausgänge: dangerouslySetInnerHTML, v-html, |safe, innerHTML sowie URLs oder Inline-Event-Handler, die aus Nutzerdaten gebaut werden. Kodieren Sie exakt für den jeweiligen Kontext, und bereinigen Sie Rich-HTML mit einer spezialisierten Bibliothek wie DOMPurify statt mit einer Regex.

Wo die Daten landenKodieren alsBeispiel
HTML-BodyHTML-Entities< wird zu &lt;, " wird zu &quot;
HTML-AttributEntities in einem Attribut mit AnführungszeichenAttributwert immer in Anführungszeichen setzen; " und ' kodieren
JavaScriptNicht in Skripttext einfügen; Daten über data--Attribute oder einen JSON-Block <script type="application/json"> übergeben</script> in einem String wird zu \u003c/script\u003e
URL-ParameterProzentkodierungencodeURIComponent(value)
CSS-WertGanz vermeiden; Klassennamen aus einer Allowlist wählenNutzereingaben nie in style interpolieren

SSRF, Datei-Uploads und Deserialisierung

Server-Side Request Forgery (SSRF): Ruft Ihr Server eine von Nutzern angegebene URL ab (Webhooks, Bild-Proxys, Link-Vorschauen), kann ein Angreifer ihn auf interne Dienste oder den Cloud-Metadaten-Endpunkt 169.254.169.254 richten und Zugangsdaten auslesen. Lösen Sie zuerst den Hostnamen auf, lehnen Sie private und Link-Local-Bereiche ab, deaktivieren Sie Weiterleitungen und betreiben Sie Fetcher in einem Netzwerksegment, das nichts Internes erreichen kann.

Datei-Uploads: Prüfen Sie den Typ anhand des Inhalts, nicht anhand der Dateiendung oder des vom Client gesendeten Content-Type; erzwingen Sie eine Größenbegrenzung; speichern Sie Dateien außerhalb des Web-Roots oder in einem Object Storage unter einem von Ihnen erzeugten Zufallsnamen; und liefern Sie sie nach Möglichkeit von einem separaten Origin mit nosniff und Content-Disposition: attachment aus. Ein Upload darf nie an einem Ort landen, an dem der Webserver ihn ausführt.

Deserialisierung und Mass Assignment: Deserialisieren Sie niemals nicht vertrauenswürdige Daten mit einem Format, das beliebige Klassen instanziieren kann (native Java-Serialisierung, Python pickle, PHP unserialize, YAML mit Custom Tags); verwenden Sie JSON mit einem Schema. Binden Sie Request-Bodys an eine explizite Allowlist von Feldern, damit ein Nutzer nicht "role": "admin" in ein Modell posten kann, das zufällig diese Spalte hat.

Broken Access Control: Das Risiko Nummer eins

Broken Access Control steht seit 2021 an der Spitze der OWASP Top 10 und behält diesen Platz als A01:2025. Es ist kein einzelner Bug, sondern eine Gewohnheit: zu prüfen, wer jemand ist (Authentifizierung), und dabei zu vergessen, bei jeder Anfrage zu prüfen, worauf er zugreifen darf (Autorisierung). Die klassische Form ist die Insecure Direct Object Reference: GET /api/invoices/1042 funktioniert für den Eigentümer der Rechnung – und für jeden, der die Nummer ändert.

  • Standardmäßig verweigern. Jede Route braucht eine explizite Regel, die Zugriff gewährt; eine fehlende Regel bedeutet 403, nicht 200.
  • Serverseitig und pro Objekt prüfen. Einen Button in der Oberfläche auszublenden ist keine Zugriffskontrolle. Jeder Lese- und Schreibzugriff muss bestätigen, dass der aktuelle Nutzer den konkreten Datensatz besitzt oder darauf zugreifen darf – auch in Bulk-Endpunkten, Exporten und Hintergrund-Jobs.
  • Nicht erratbare IDs verwenden, wo es hilft (UUIDs), sich aber nie darauf verlassen: Verschleierung ist keine Autorisierung.
  • CORS abriegeln. Access-Control-Allow-Origin: * mit Credentials oder das Zurückspiegeln jedes beliebigen Origin aus der Anfrage liefert Ihre API jeder Website aus, die der Nutzer besucht.
  • Verzeichnislisten deaktivieren, .git, .env, Backup- und Konfigurationsdateien auf Webserver-Ebene blockieren und Admin-Panels aus dem öffentlichen Internet heraushalten oder hinter MFA und IP-Allowlists stellen.
  • Autorisierungsfehler begrenzen und protokollieren. Eine Häufung von 403-Antworten aus einer Session ist ein laufender Enumerationsangriff.
javascript
// Express: ownership check on every object access
app.get("/api/invoices/:id", requireAuth, async (req, res) => {
  const invoice = await Invoice.findById(req.params.id);
  if (!invoice || invoice.ownerId !== req.user.id) {
    return res.status(404).end(); // 404, not 403: don't confirm the record exists
  }
  res.json(invoice);
});

Schicht 5: Abhängigkeiten und Software-Lieferkette

Der größte Teil des Codes einer typischen Webanwendung ist heruntergeladen, nicht selbst geschrieben. Deshalb debütieren Software Supply Chain Failures auf A03 der OWASP Top 10 von 2025, und deshalb hat die Ausnutzung von Schwachstellen im DBIR 2026 Phishing und gestohlene Zugangsdaten überholt. Im September 2025 schleuste ein einziger gephishter Maintainer Krypto-stehlende Malware in chalk, debug und 16 weitere npm-Pakete ein, die zusammen über zwei Milliarden Downloads pro Woche haben; jedes Projekt, das im Zeitfenster eine nicht festgelegte Version installierte, zog sie automatisch mit.

  • Committen Sie ein Lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml, poetry.lock, go.sum) und installieren Sie in der CI mit npm ci, damit Builds reproduzierbar sind und kein neues Upstream-Release ungeprüft hineinrutscht.
  • Scannen Sie kontinuierlich: npm audit, pip-audit, bundler-audit, GitHub Dependabot oder Renovate für Updates und einen Container-Scanner wie Trivy oder Grype für die Betriebssystemebene.
  • Verzögern Sie Upgrades ohne Sicherheitsbezug um einige Tage (minimumReleaseAge in Renovate), damit ein vergiftetes Release meist schon zurückgezogen ist, bevor Sie es übernehmen – Sicherheitspatches spielen Sie dagegen sofort ein.
  • Pinnen Sie Actions und Skripte von Drittanbietern in der CI auf einen Commit-SHA, und verwenden Sie Subresource Integrity (integrity="sha384-...") für jedes Skript, das Sie von einem öffentlichen CDN laden.
  • Geben Sie der CI minimale Rechte: wo möglich schreibgeschützte Tokens, kurzlebige OIDC-Credentials statt langlebiger Secrets und Veröffentlichungsrechte nur für einen Release-Job.
  • Erzeugen Sie beim Build eine SBOM (CycloneDX oder SPDX), damit Sie die Frage „Sind wir betroffen?“ in Minuten beantworten können, wenn die nächste CVE vom Kaliber Log4Shell auftaucht.
bash
# Reproducible install + audit in CI
npm ci --ignore-scripts
npm audit --audit-level=high

# Pin a GitHub Action to a commit, not a floating tag
# uses: actions/checkout@v4                 <- can change underneath you
# uses: actions/checkout@<full-commit-sha>  # v4.2.2

# Subresource Integrity for a CDN script (hash from: openssl dgst -sha384 -binary lib.min.js | openssl base64 -A)
<script src="https://cdn.example.com/lib.min.js"
        integrity="sha384-<base64-hash>"
        crossorigin="anonymous"></script>

npm ci --ignore-scripts blockiert die Install-Skripte, über die sich die meiste npm-Malware ausführt; aktivieren Sie Skripte danach gezielt nur für die wenigen Pakete, die wirklich einen Build-Schritt brauchen.

Wenn Sie WordPress oder ein anderes CMS betreiben, gelten dieselben Regeln für Plugins und Themes – dort beginnen die meisten CMS-Kompromittierungen. Halten Sie den Core und jedes Plugin aktuell, löschen Sie alles Ungenutzte, und prüfen Sie mit dem CMS-Detector, was ein Scanner über Ihre Versionen herausfinden kann.

Schicht 6: Server-Härtung: Ports, Patches, Secrets und Backups

Die Anwendungsschicht ist bedeutungslos, wenn der Server darunter Passwort-Logins per SSH akzeptiert, eine Datenbank auf einem öffentlichen Port betreibt oder seit seiner Einrichtung nie gepatcht wurde. Best Practices für Server sind langweilig – und genau hier dringt Ransomware ein.

Schließen Sie jeden Port, den Sie nicht bedienen

Ein öffentlicher Webserver braucht offene Ports 80 und 443 sowie SSH aus Ihrem eigenen IP-Bereich. Datenbanken (3306, 5432, 27017), Redis (6379), Elasticsearch (9200), Admin-Panels und Metrik-Endpunkte sollten nur an localhost oder ein privates Netzwerk gebunden sein. Prüfen Sie nach jeder Änderung von außen mit dem Port-Checker – das ist die Sicht, die ein Angreifer hat, und Cloud-Security-Groups sind leicht falsch zu lesen.

bash
# Ubuntu: default-deny firewall, allow only web + SSH from your office range
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp
sudo ufw enable   # check your own IP is in that range first, or you lock yourself out

# SSH: keys only, no root password login, in a drop-in that sshd reads first
printf 'PasswordAuthentication no\nPermitRootLogin prohibit-password\n' \
  | sudo tee /etc/ssh/sshd_config.d/00-hardening.conf
sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin) '   # what sshd will really use
sudo systemctl reload ssh

Unter Ubuntu und Debian liest sshd die Dateien in /etc/ssh/sshd_config.d/ vor dem Rest von sshd_config, und für jede Einstellung gilt der zuerst gelesene Wert. Deshalb schreiben die obigen Befehle eine Drop-in-Datei namens 00-hardening.conf: Eine Änderung weiter unten in der Hauptdatei verliert gegen das Drop-in eines Cloud-Images, das PasswordAuthentication yes setzt. Bestätigen Sie das Ergebnis mit sudo sshd -T, bevor Sie sich abmelden. Im Port-Checker erscheint ein Port, den Ihre Firewall verwirft, als filtered (keine Antwort), einer ohne lauschenden Dienst als closed: beides ist in Ordnung, open ist der, den Sie beheben sollten.

Nach Plan patchen, Secrets aus dem Code halten

Aktivieren Sie unbeaufsichtigte Sicherheitsupdates für das Betriebssystem, abonnieren Sie die Security-Mailinglisten Ihrer Runtime und Ihres Frameworks, und behandeln Sie eine kritische CVE in allem, was aus dem Internet erreichbar ist, als Aufgabe für denselben Tag. Betreiben Sie Dienste als unprivilegierte Benutzer, in Containern oder mit systemd-Sandboxing, damit ein kompromittierter Prozess nicht die ganze Maschine auslesen kann.

Secrets (Datenbankpasswörter, API-Schlüssel, Signaturschlüssel) gehören niemals ins Repository, in eine Docker-Image-Schicht oder in clientseitiges JavaScript. Laden Sie sie aus Umgebungsvariablen, die beim Deployment injiziert werden, oder aus einem Secrets-Manager, rotieren Sie sie, wenn jemand mit Zugriff das Team verlässt, und durchsuchen Sie die Repository-Historie mit einem Tool wie gitleaks – denn ein einmal committeter Schlüssel ist für immer kompromittiert, auch wenn der Commit später entfernt wird.

Ransomware-feste Backups und ein CDN davor

Befolgen Sie die 3-2-1-Regel: drei Kopien auf zwei verschiedenen Medien, eine davon außer Haus – und machen Sie mindestens eine Kopie unveränderlich oder offline, damit Ransomware, die den Server erreicht, nicht auch die Backups verschlüsseln kann. Verschlüsseln Sie Backups, schließen Sie die Datenbank und das Upload-Verzeichnis ein, und – ganz entscheidend – testen Sie regelmäßig eine Wiederherstellung. Ein Backup, aus dem nie jemand etwas wiederhergestellt hat, ist eine Hoffnung, kein Plan. Die Wiederherstellungszeit entscheidet, ob ein Vorfall ein bloßer Ausfall bleibt oder das Ende des Unternehmens bedeutet.

Stellen Sie ein CDN oder eine WAF (Cloudflare, Fastly, AWS CloudFront mit WAF oder das Pendant Ihres Hosters) vor den Origin. Es fängt volumetrische DDoS-Angriffe ab, wendet verwaltete Regeln gegen gängige Injection-Payloads und schädliche Bots an, verbirgt die IP Ihres Origins und bietet Ihnen einen Ort, um Rate Limits und Geo-Regeln durchzusetzen, ohne die Anwendung anzufassen. Beschränken Sie dann die Firewall des Origins so, dass nur die IP-Bereiche des CDN Port 443 direkt erreichen; sonst gehen Angreifer einfach daran vorbei. Der Hosting-Checker zeigt, welches CDN vor einer Website sitzt und was öffentliche Belege über den Host dahinter aussagen.

E-Mail-Authentifizierung: SPF, DKIM und DMARC

Zur Web-Sicherheit gehört auch die E-Mail, die Ihre Passwort-Resets, Rechnungen und Support-Antworten transportiert. Ohne SPF, DKIM und DMARC kann jeder Mail als billing@yourdomain.com versenden, und seit Februar 2024 verlangen Google und Yahoo alle drei von Massenversendern, Microsoft seit Mai 2025 dasselbe für Outlook.com. Das vollständige Set sind drei DNS-TXT-Einträge:

dns
yourdomain.com.                    TXT  "v=spf1 include:_spf.google.com -all"
google._domainkey.yourdomain.com.  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."
_dmarc.yourdomain.com.             TXT  "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; adkim=s; aspf=s"

DMARC p=reject ist zugleich eine Maßnahme zum Markenschutz: Nur so verhindern Sie, dass eine Phishing-Kampagne exakt Ihre Domain in die Absenderzeile setzt. Die aggregierten Berichte (rua=) zeigen Ihnen, wer es versucht.

Starten Sie DMARC mit p=none, um Berichte zu sammeln, und wechseln Sie zu p=quarantine und dann zu p=reject, sobald jeder legitime Absender (Marketing-Plattform, Helpdesk, CRM) das Alignment besteht. Ergänzen Sie MTA-STS- und TLS-RPT-Einträge, um die verschlüsselte Zustellung an Ihre Mailserver zu erzwingen. Veröffentlichen Sie auf Domains, die nie Mail senden oder empfangen, einen Null-MX (MX 0 .), v=spf1 -all und einen DMARC-Eintrag mit p=reject: Der Null-MX sagt nur, dass die Domain keine Mail annimmt – erst SPF und DMARC lassen Empfänger Fälschungen ablehnen. Prüfen Sie jeden Eintrag mit dem SPF-Checker, dem DKIM-Checker und dem DMARC-Checker und gleichen Sie Ihre Versand-IPs bei sinkender Zustellbarkeit mit dem IP-Blacklist-Checker gegen Sperrlisten ab.

Protokollieren, überwachen und für den Ernstfall planen

Zwei der zehn OWASP-Kategorien von 2025 drehen sich darum, was nach einem Fehler passiert: Security Logging and Alerting Failures (A09) und die neue Kategorie Mishandling of Exceptional Conditions (A10). Der typische Einbruch bleibt noch immer monatelang unentdeckt, weil die Spuren nie aufgezeichnet wurden – oder aufgezeichnet wurden und niemand hingesehen hat.

  • Protokollieren Sie Sicherheitsereignisse mit Kontext: jeden erfolgreichen und fehlgeschlagenen Login, MFA-Änderungen, Passwort-Resets, Rechteänderungen, verweigerte Zugriffe, fehlgeschlagene Eingabevalidierungen und Admin-Aktionen, jeweils mit Zeitstempel, Benutzer-ID, Quell-IP und User-Agent.
  • Protokollieren Sie niemals Secrets: Passwörter, Session-Tokens, vollständige Kartennummern, API-Schlüssel. Maskieren Sie sie in der Logging-Schicht, nicht an jeder einzelnen Aufrufstelle.
  • Leiten Sie Logs vom Server weg in einen zentralen Speicher (CloudWatch, Loki, Elastic, ein SIEM) mit mindestens 90 Tagen Aufbewahrung, damit ein Angreifer mit Root-Rechten seine Spuren nicht verwischen kann.
  • Alarmieren Sie bei Mustern, nicht bei Einzelereignissen: 50 fehlgeschlagene Logins in einer Minute, eine Häufung von 403-Antworten aus einer Session, ein außerhalb der Geschäftszeiten angelegter neuer Admin, ein Zertifikat für Ihre Domain, das Sie nicht beantragt haben.
  • Im Zweifel blockieren (Fail Closed): Wenn eine nachgelagerte Prüfung (Auth-Dienst, Rate Limiter, WAF) einen Fehler liefert, lehnen Sie die Anfrage ab. A10 gibt es, weil so viele Systeme Zugriff gewähren, wenn die Prüfung, die ihn hätte blockieren sollen, eine Exception wirft.
  • Von außen überwachen: Verfügbarkeit, Zertifikatsablauf, DNS-Änderungen, Sperrlisten-Einträge und Header-Rückschritte. Führen Sie nach jedem Deployment den SSL-Checker, den HTTP-Header-Checker und den DNS-Health-Check (40 Prüfungen zu Delegation, Nameservern, DNSSEC und SPF/DMARC) erneut aus.

Schreiben Sie den Incident-Response-Plan, bevor Sie ihn brauchen

Legen Sie vorab fest, wer Bereitschaft hat, wie alle Zugangsdaten rotiert werden, wie Sie die Website in den Nur-Lese-Modus versetzen, wo die sauberen Backups liegen und welche Aufsichtsbehörde oder Kunden innerhalb von wie vielen Stunden informiert werden müssen (72 nach DSGVO). Führen Sie einmal im Jahr eine Tabletop-Übung durch. Ein geübter Plan macht aus Tagen des Improvisierens eine Checkliste.

Veröffentlichen Sie eine security.txt-Datei unter /.well-known/security.txt (RFC 9116) mit einer Contact:-Zeile und einem Expires:-Datum – den beiden Pflichtfeldern (ein Encryption:-Schlüssel ist optional). Sicherheitsforscher, die einen Bug in Ihrer Website finden, schauen zuerst dort nach; ohne sie finden sie womöglich niemanden, dem sie es melden können.

Testen: Scanner, Penetrationstests und laufende Prüfungen

Jede Maßnahme oben lässt sich überprüfen, und die Prüfung sollte wo immer möglich automatisiert sein, damit sie nicht verkümmert. Eine sinnvolle Stufenleiter, von kostenlos und sofort bis periodisch und kostenpflichtig:

PrüfungToolWie oft
TLS-Konfiguration, Kette, AblaufSSL-Checker, SSL Labs, testssl.shNach jeder Zertifikats- oder Serveränderung; Ablauf täglich
Sicherheitsheader und CSPHTTP-Header-Checker, MDN HTTP ObservatoryNach jedem Deployment (in die CI aufnehmen)
Offene PortsPort-Checker, nmap von außerhalb Ihres NetzwerksNach jeder Firewall- oder Cloud-Änderung
DNS, DNSSEC, E-Mail-AuthentifizierungDNS-Health-Check, DMARC-CheckerMonatlich und nach jeder DNS-Änderung
Veraltete SubdomainsSubdomain-FinderVierteljährlich und bei jeder Stilllegung
Abhängigkeiten mit bekannten Schwachstellennpm audit, Dependabot, TrivyBei jedem Build
Schwachstellen im Code (SAST)Semgrep, CodeQLBei jedem Pull Request
Web-Schwachstellen zur Laufzeit (DAST)ZAP, NucleiWöchentlich gegen Staging
Autorisierung und GeschäftslogikManueller Penetrationstest oder Bug-Bounty-ProgrammJährlich und nach größeren Features

Scanner sind gut bei Injection, Headern und veralteten Komponenten und schlecht bei Autorisierung und Geschäftslogik – planen Sie daher für alles, was mit Geld oder personenbezogenen Daten umgeht, mindestens einen manuellen Test pro Jahr ein. Beheben Sie Funde nach Angriffsfläche: Was ein nicht angemeldeter Nutzer aus dem Internet ausnutzen kann, kommt zuerst.

Die Checkliste für Website-Sicherheit

Kopieren Sie sie in die README Ihres Projekts oder in Ihren Ticket-Tracker. Jede Zeile entspricht einer der Maßnahmen oben und ist so formuliert, dass sie sich als erledigt oder nicht erledigt abhaken lässt; die letzte Spalte ist der Nachweis.

SchichtMaßnahmeErledigt, wenn
DomainRegistrar Lock und MFA für das Registrar-Konto; automatische Verlängerung aktivWHOIS zeigt clientTransferProhibited; Ablauf mehr als 12 Monate entfernt
DNSDNSSEC-signiert; CAA-Eintrag nennt nur Ihre CAsdig +dnssec liefert RRSIG; DS-Eintrag in der übergeordneten Zone vorhanden
DNSKeine verwaisten CNAME- oder A-EinträgeJeder Hostname aus dem Subdomain-Finder zeigt auf etwas, das Sie kontrollieren
TLSNur TLS 1.2+, TLS 1.3 bevorzugt, vollständige Kette ausgeliefertSSL-Checker: Kette vollständig, TLS 1.0/1.1 abgelehnt
TLSHSTS mit einem Jahr max-age und includeSubDomains (Preload optional)Der HTTP-Header-Checker besteht den HSTS-Test
TLSErneuerung per ACME automatisiert; Ablauf überwachtcertbot renew --dry-run läuft durch; Alarm bei 14 Tagen eingerichtet
HeaderCSP (Nonce-basiert), frame-ancestors, nosniff, Referrer-Policy, Permissions-PolicyHTTP-Header-Checker: Note A oder A+
AuthHashing mit Argon2id oder bcrypt; NIST-Passwortregeln; Abgleich mit Leak-ListenEin Hash dauert 100 bis 250 ms; keine Kompositionsregeln
AuthMFA für alle angeboten, für Admins Pflicht; Passkeys unterstütztAdmin-Login ohne zweiten Faktor unmöglich
AuthLogin-, Reset- und MFA-Endpunkte pro IP und pro Konto begrenztSechs schnelle Versuche von einer IP: der sechste liefert 429
Sessions__Host--Cookie mit Secure, HttpOnly, SameSite; ID beim Login rotiertCookie-Attribute in den DevTools sichtbar; alte Session nach Login ungültig
EingabenÜberall parametrisierte Abfragen; Ausgabe kontextgerecht kodiert; Uploads anhand des Inhalts validiertCodesuche findet keine zusammengebauten Query-Strings; XSS-Payloads erscheinen als Text
ZugriffskontrolleRouting nach Deny-by-Default; Eigentümerprüfung pro Objekt; strikte CORS-RegelnAbspielen fremder IDs liefert 404 oder 403
AbhängigkeitenLockfile committet; npm ci; Audit in der CI; Actions auf SHA gepinnt; SRI für CDN-SkripteBuild schlägt bei einer CVE mit hohem Schweregrad fehl
ServerNur 80 und 443 öffentlich; SSH nur mit Schlüssel; unbeaufsichtigte Sicherheitsupdates; Secrets in Env oder VaultDer Port-Checker zeigt 3306 und 6379 als closed oder filtered, und 22 ebenfalls von außerhalb Ihres eigenen Bereichs
Backups3-2-1 mit einer unveränderlichen Kopie; Wiederherstellung getestetLetzter erfolgreicher Wiederherstellungstest liegt höchstens 90 Tage zurück
E-MailSPF -all, DKIM, DMARC p=reject, MTA-STSDMARC-Checker besteht; aggregierte Berichte gehen ein
MonitoringAuthentifizierungs- und Autorisierungsereignisse zentral protokolliert; Alarme bei Mustern; externes Monitoring von Verfügbarkeit, Zertifikaten und DNSTestalarm ausgelöst und empfangen
ReaktionSchriftlicher Incident-Plan; security.txt veröffentlicht; Tabletop-Übung durchgeführtPlan in den letzten 12 Monaten überprüft

So passt das zu den OWASP Top 10:2025

Die OWASP Top 10 sind die meistzitierte Liste von Risiken für Webanwendungen; die Ausgabe 2025 hat die Reihenfolge neu gemischt und zwei neue Kategorien eingeführt. Wenn ein Kunde, Auditor oder Compliance-Framework fragt, wie Sie damit umgehen, ist dies die Zuordnung zu den Maßnahmen in diesem Leitfaden:

OWASP Top 10:2025Maßnahmen in diesem Leitfaden
A01 Broken Access ControlDeny by Default, Prüfungen pro Objekt, strikte CORS-Regeln, abgeschottete Admin-Bereiche
A02 Security MisconfigurationSicherheitsheader, HSTS, geschlossene Ports, entfernte Versions-Header, Verzeichnislisten deaktiviert
A03 Software Supply Chain Failures (neu)Lockfiles, Audits, gepinnte Actions, SRI, SBOM, CI mit minimalen Rechten
A04 Cryptographic FailuresTLS 1.2+ und 1.3, HSTS, Argon2id, Secrets-Management, verschlüsselte Backups
A05 InjectionParametrisierte Abfragen, Output-Encoding, CSP, Upload-Validierung
A06 Insecure DesignBedrohungsmodell pro Schicht, Fail-Closed-Voreinstellungen, Rate Limiting als Designprinzip
A07 Authentication FailuresNIST-Passwortregeln, Leak-Prüfungen, MFA und Passkeys, Session-Rotation
A08 Software or Data Integrity FailuresSRI, signierte und gepinnte Abhängigkeiten, sichere Deserialisierung
A09 Security Logging and Alerting FailuresZentrales Logging, Alarme bei Mustern, externes Monitoring
A10 Mishandling of Exceptional Conditions (neu)Fail Closed, einheitliche Fehlerantworten, keine Stacktraces an Nutzer

Der ASVS von OWASP (Application Security Verification Standard) macht aus demselben Material eine nummerierte Checkliste für Audits. Level 1 ist ein realistisches Ziel für jede öffentliche Website, Level 2 für alles, was personenbezogene oder finanzielle Daten verarbeitet.

Prüfen Sie die Sicherheitsheader Ihrer Website in Sekunden

Der kostenlose HTTP-Header-Checker von DNS Robot zeigt die Antwort-Header jeder URL genau so, wie der Server sie sendet, und bewertet die Sicherheitsheader mit den Tests des Mozilla HTTP Observatory – mit der Lösung für jeden fehlenden. Ohne Anmeldung.

Quellen

  1. 2026 Data Breach Investigations Report, Verizon
  2. OWASP Top 10:2025, OWASP
  3. Password Storage Cheat Sheet, OWASP
  4. SP 800-63B-4: Authentication and Authenticator Management, NIST
  5. Ballot SC-081v3: reducing certificate validity and data reuse periods, CA/Browser Forum
  6. HTTPS by default, Google
  7. RFC 9116: A File Format to Aid in Security Vulnerability Disclosure, IETF

Häufige Fragen zur Website-Sicherheit

Was sind die wichtigsten Best Practices für Website-Sicherheit?

Erzwingen Sie HTTPS mit modernem TLS und HSTS, senden Sie strikte Sicherheitsheader (vor allem eine Content Security Policy), hashen Sie Passwörter mit Argon2id und sichern Sie Logins mit MFA und Rate Limiting ab, verwenden Sie parametrisierte Abfragen und Output-Encoding, setzen Sie die Zugriffskontrolle serverseitig für jedes Objekt durch, halten Sie Abhängigkeiten gepatcht und gepinnt, schließen Sie ungenutzte Ports und protokollieren Sie Sicherheitsereignisse zentral. Sichern Sie zuerst Domain und DNS ab, denn alles andere setzt voraus, dass Sie Ihren Namen noch kontrollieren.

Was sind die OWASP Top 10 und sind sie 2026 noch relevant?

Die OWASP Top 10 sind eine von der Community gepflegte Rangliste der kritischsten Sicherheitsrisiken für Webanwendungen. Die Ausgabe 2025 umfasst Broken Access Control, Security Misconfiguration, Software Supply Chain Failures, Cryptographic Failures, Injection, Insecure Design, Authentication Failures, Software or Data Integrity Failures, Security Logging and Alerting Failures sowie Mishandling of Exceptional Conditions. Sie bleiben die Referenz, auf die sich die meisten Audits, Frameworks und Kunden berufen.

Welche HTTP-Security-Header sollte jede Website senden?

Mindestens: Strict-Transport-Security, Content-Security-Policy (einschließlich frame-ancestors), X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin und Permissions-Policy. X-Frame-Options: DENY ist ein Legacy-Fallback für frame-ancestors, und Cross-Origin-Opener-Policy: same-origin ist eine günstige Ergänzung. Entfernen Sie Server und X-Powered-By, damit Scanner Ihre Softwareversionen nicht auslesen können.

Reicht HTTPS aus, um eine Webseite abzusichern?

Nein. HTTPS verschlüsselt den Datenverkehr zwischen Browser und Server; gegen Injection, Broken Access Control, schwache Passwörter, verwundbare Abhängigkeiten oder einen offenen Datenbank-Port tut es nichts. Es ist die Basisschicht, und HSTS macht sie verbindlich: Hat ein Browser den Header einmal gesehen, sendet er nie wieder eine reine HTTP-Anfrage an Ihre Domain.

Wie speichere ich Benutzerpasswörter sicher?

Niemals im Klartext und niemals mit einem schnellen Hash wie MD5 oder SHA-256. Verwenden Sie Argon2id (19 MiB Speicher, 2 Iterationen) oder bcrypt mit einem Work Factor von 10 oder höher, mit individuellem Salt pro Passwort und so abgestimmt, dass ein Hash etwa 100 bis 250 ms dauert. Prüfen Sie neue Passwörter gegen eine Leak-Liste und verlangen Sie MFA für privilegierte Konten.

Was ist eine Content Security Policy und brauche ich eine?

Eine CSP ist ein HTTP-Header, der dem Browser mitteilt, aus welchen Quellen eine Seite Skripte, Styles, Frames und andere Ressourcen laden darf. Eine Nonce-basierte CSP mit 'strict-dynamic' stoppt die meisten Cross-Site-Scripting-Angriffe selbst dann, wenn eine Injection-Lücke existiert. Jede Website, die nutzergenerierte Inhalte darstellt oder Skripte von Drittanbietern lädt, sollte eine haben; starten Sie im Report-Only-Modus und schalten Sie auf Durchsetzung um, sobald die Verstoßberichte sauber sind.

Wie prüfe ich, ob meine Website sicher ist?

Beginnen Sie mit den Prüfungen von außen: ein SSL-Check für TLS-Version, Kette und Ablauf; ein HTTP-Header-Check für Sicherheitsheader; ein Port-Check für offene Dienste und ein DNS-Health-Check für DNSSEC und SPF/DMARC. Scannen Sie danach die Abhängigkeiten mit npm audit oder dem Gegenstück Ihres Stacks, lassen Sie ZAP gegen eine Staging-Kopie laufen und testen Sie die Zugriffskontrolle manuell, indem Sie Anfragen als anderer Benutzer wiederholen.

Warum werden TLS-Zertifikate immer kurzlebiger?

Das CA/Browser Forum hat beschlossen, die maximale Zertifikatslaufzeit von 398 Tagen auf 200 Tage (15. März 2026), 100 Tage (15. März 2027) und 47 Tage (15. März 2029) zu senken, weil kürzere Laufzeiten den Schaden durch einen gestohlenen Schlüssel oder ein fehlerhaft ausgestelltes Zertifikat begrenzen und die Abhängigkeit vom Widerruf verringern. Praktisch bedeutet das: Die Erneuerung muss per ACME automatisiert werden.

Wie oft sollte ich die Abhängigkeiten meiner Website aktualisieren?

Spielen Sie Sicherheitspatches ein, sobald sie erscheinen – bei allem, was aus dem Internet erreichbar ist, idealerweise innerhalb von 24 Stunden –, und lassen Sie bei jedem Build ein automatisches Audit laufen. Bei Updates ohne Sicherheitsbezug ist eine kurze Verzögerung von einigen Tagen sicherer, weil kompromittierte Paketversionen meist schnell zurückgezogen werden; Tools wie Renovate können diese Verzögerung automatisch durchsetzen.

Werden kleine Websites wirklich angegriffen?

Ja, ständig, denn Angriffe laufen automatisiert und wählen ihre Ziele nicht nach Größe aus. Scanner durchsuchen jede öffentliche IP-Adresse nach offenen Ports und bekannten CMS-Schwachstellen, und Credential-Stuffing-Tools probieren geleakte Passwörter an jedem Login-Formular aus, das sie finden. Eine kleine Website ist zudem wertvoll als Phishing-Host, Spam-Relay oder Brückenkopf zu einem größeren Kunden.

Über den Autor

Shaik Vahid

Gründer von DNS Robot. Vahid hat jahrelang im Webhosting-Support Domains, DNS-Einträge, SSL-Zertifikate und E-Mail-Zustellung für Kunden in Ordnung gebracht. Er entwickelt die Tools von DNS Robot und schreibt diese Anleitungen über die Fehler, die Menschen wirklich sehen.

HTTP-Header-Checker

HTTP-Antwort-Header und Sicherheits-Header-Bewertung analysieren