Skip to content
Zurück zum Blog
Sicherheit

Web-Sicherheit: Hashing, Validierung und Authentifizierung

Web-Sicherheit meistern: bcrypt vs Argon2 Passwort-Hashing, XSS- und SQL-Injection-Prävention, JWT Best Practices, CSP-Header und MFA-Implementierung — mit Code-Beispielen in JavaScript.

12 Min. Lesezeit

Sicherheits-Best-Practices für Webentwickler

Dieser Leitfaden behandelt die wesentlichen Sicherheitspraktiken für Webentwickler: Passwort-Hashing, Eingabevalidierung, Authentifizierung und Sicherheitsheader.

Passwortsicherheit

Speichere Passwörter niemals im Klartext

Hashe Passwörter immer mit modernen Algorithmen wie bcrypt, Argon2 oder scrypt. Diese Algorithmen sind absichtlich langsam, was Brute-Force-Angriffe unpraktikabel macht.

// Gut: Verwendung von bcrypt
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);

Hashing-Algorithmen im Vergleich

Nicht alle Hashing-Algorithmen sind gleich. Die Wahl des richtigen hängt von deinem Bedrohungsmodell und Anwendungsfall ab:

AlgorithmusAusgabegrößeGeschwindigkeitAnwendungsfallSicherheitsstatus
MD5128-BitSehr schnellPrüfsummen, nicht-sicherheitsrelevante HashesFür Sicherheit gebrochen
SHA-256256-BitSchnellDatenintegrität, digitale SignaturenSicher
bcrypt184-BitLangsam (einstellbar)Passwort-HashingSicher
Argon2KonfigurierbarLangsam (einstellbar)Passwort-Hashing (modern)Empfohlen für neue Projekte

bcrypt und Argon2 sind absichtlich langsam. Jede Hash-Operation dauert zehn oder hunderte Millisekunden, was großangelegte Brute-Force-Angriffe wirtschaftlich unmöglich macht.

Passwort-Entropie verstehen

Passwortstärke kann mathematisch mittels Entropie gemessen werden: entropy = log2(charset_size^length). Ein Passwort mit Kleinbuchstaben (26 Zeichen) und 8 Zeichen hat ~37,6 Bits Entropie. Ein 16-Zeichen-Passwort mit Groß-, Kleinbuchstaben, Ziffern und Symbolen (95 Zeichen) hat ~105 Bits, also exponentiell schwerer zu knacken. Deshalb ist Länge für die meisten Nutzer wichtiger als Komplexität. Die Mathematik dahinter erklärt unser Passwort-Entropie-Leitfaden.

Passwort-Manager verwenden

Empfiehl deinen Nutzern einen Passwort-Manager. Von Menschen gewählte Passwörter folgen tendenziell vorhersagbaren Mustern, die Angreifer mit Wörterbuch-Angriffen ausnutzen. Passwort-Manager erzeugen wirklich zufällige Strings und eliminieren die Wiederverwendung von Passwörtern über Dienste hinweg, einer der häufigsten Vektoren für Credential-Stuffing-Angriffe.

Ausreichende Salt-Runden verwenden

Salt-Runden bestimmen den Rechenaufwand. Höher ist sicherer, aber langsamer. 10–12 Runden sind ein guter Kompromiss für die meisten Anwendungen.

Eingabevalidierung

Auf Client und Server validieren

Client-seitige Validierung verbessert die UX, aber Server-seitige Validierung ist für die Sicherheit unerlässlich. Vertraue niemals Client-Eingaben.

Alle Nutzereingaben bereinigen

Verhindere Injection-Angriffe durch Bereinigung der Eingaben:

  • Nutze parametrisierte Abfragen für SQL
  • Escape HTML-Ausgabe zur Verhinderung von XSS
  • Validiere Datei-Uploads strikt

Konkrete Angriffsbeispiele

Beispiel: Ein Kommentarformular, das Nutzereingaben direkt in HTML rendert. Ein Angreifer sendet:

<script>alert('xss')</script>

Wenn die Anwendung dies ohne Escaping rendert, führt das Skript im Browser jedes Besuchers aus: Cookies stehlen, Nutzer umleiten oder Keylogger injizieren. Die Lösung: Ausgabe immer kontextbezogen kodieren. Verwende Bibliotheken wie DOMPurify für HTML-Bereinigung.

SQL-Injection ist ebenso gefährlich. In einem Login-Formular gibt ein Angreifer als Benutzername ein:

' OR 1=1 --

Wenn die Abfrage durch String-Verkettung ("SELECT * FROM users WHERE username='" + input + "'") erstellt wird, umgeht dies die Authentifizierung vollständig. Das -- kommentiert den Rest der Abfrage aus. Die Lösung: Immer parametrisierte Abfragen (auch Prepared Statements genannt) verwenden. Jede wichtige Datenbankbibliothek unterstützt sie:

// FALSCH: String-Verkettung
db.query(`SELECT * FROM users WHERE username='${input}'`);

// RICHTIG: Parametrisierte Abfrage
db.query('SELECT * FROM users WHERE username = $1', [input]);

Content Security Policy (CSP)

Als Defense-in-Depth setze Content-Security-Policy-Header ein. CSP teilt dem Browser mit, welche Inhaltsquellen vertrauenswürdig sind, und blockiert effektiv Inline-Skripte und unautorisiertes Laden von Ressourcen. Selbst wenn eine XSS-Schwachstelle in deinem Code existiert, kann eine strikte CSP die Ausführung des injizierten Skripts verhindern. Starte mit Content-Security-Policy: default-src 'self' und füge schrittweise Ausnahmen hinzu.

Hash-Funktionen

Den richtigen Hash wählen

Verschiedene Anwendungsfälle erfordern verschiedene Hash-Funktionen:

AnwendungsfallEmpfohlen
Passwörterbcrypt, Argon2
IntegritätSHA-256
PrüfsummenSHA-256, MD5 (nicht-sicherheitsrelevant)
Schnelles HashingBLAKE3

Hash-Ausgabe und Kollisionen verstehen

MD5 erzeugt einen 128-Bit (32 Hex-Zeichen) Hash, während SHA-256 einen 256-Bit (64 Hex-Zeichen) Hash erzeugt. Dieser Unterschied ist relevant: Ein größerer Ausgaberaum bedeutet exponentiell mehr mögliche Hash-Werte, was Kollisionen weit weniger wahrscheinlich macht. Eine Kollision tritt auf, wenn zwei verschiedene Eingaben den gleichen Hash erzeugen. Ein Angreifer, der Kollisionen fabrizieren kann, kann digitale Signaturen fälschen oder verifizierte Daten manipulieren.

MD5-Kollisionen können auf moderner Hardware in Sekunden erzeugt werden. SHA-256 bleibt kollisionsresistent ohne bekannte praktische Angriffe. Daher die Faustregel:

  • Prüfsummen und Deduplizierung: MD5 ist akzeptabel, wenn Sicherheit kein Thema ist
  • Datenintegrität und Signaturen: SHA-256 bietet starke Kollisionsresistenz
  • Passwortspeicherung: bcrypt oder Argon2, die Salt und absichtliche Langsamkeit hinzufügen

HMAC für Nachrichtenauthentifizierung

Wenn du sowohl Integrität als auch Authentizität einer Nachricht verifizieren musst, verwende HMAC (Hash-based Message Authentication Code). HMAC kombiniert eine Hash-Funktion mit einem geheimen Schlüssel und stellt sicher, dass nur Parteien, die den Schlüssel kennen, das Tag erzeugen oder verifizieren können. Das ist essenziell für API-Authentifizierung, Webhook-Verifizierung und sichere Token-Erzeugung.

Verwende niemals MD5 oder SHA-1 für Sicherheit

MD5 und SHA-1 sind für Sicherheitszwecke gebrochen. Verwende SHA-256 oder SHA-3 für kryptografisches Hashing.

HTTPS überall

Was TLS tatsächlich macht

TLS (Transport Layer Security) bietet drei Schutzmaßnahmen: Verschlüsselung im Transit (verhindert Abhören), Server-Authentifizierung (beweist, dass du mit dem echten Server sprichst) und Datenintegrität (erkennt Manipulation während der Übertragung). Ohne TLS reist alles zwischen Nutzern und Server (Passwörter, Token, persönliche Informationen) im Klartext.

Verwende immer TLS

  • Beschaffe Zertifikate von vertrauenswürdigen CAs (Let’s Encrypt ist kostenlos und vollautomatisch)
  • Leite HTTP auf HTTPS um
  • Verwende HSTS-Header
  • Halte TLS-Versionen aktuell

HSTS und Mixed Content

HSTS-Header teilen Browsern mit, sich nur über HTTPS zu verbinden, selbst wenn der Nutzer http:// eingibt. Setze Strict-Transport-Security: max-age=31536000; includeSubDomains, um dies ein Jahr lang über alle Subdomains durchzusetzen. Das verhindert SSL-Stripping-Angriffe, bei denen ein Angreifer die Verbindung auf HTTP herabstuft.

Achte auf Mixed-Content-Warnungen: Wenn deine HTTPS-Seite Bilder, Skripte oder Stylesheets über HTTP lädt, blockieren oder warnen Browser davor. Überprüfe deine Seiten auf hartcodierte http://-URLs und verwende protokollrelative Pfade oder erzwinge HTTPS für alle Ressourcen.

Authentifizierung

Rate Limiting implementieren

Verhindere Brute-Force-Angriffe mit Rate Limiting:

  • Begrenze Login-Versuche pro IP
  • Füge Verzögerungen nach fehlgeschlagenen Versuchen hinzu
  • Verwende CAPTCHA bei verdächtiger Aktivität

JWT-Authentifizierung Grundlagen

JSON Web Tokens (JWT) bieten einen zustandslosen Authentifizierungsmechanismus, strukturiert als header.payload.signature. Der Server signiert das Token mit einem geheimen Schlüssel, und Clients fügen es in nachfolgenden Anfragen ein. Da das Token die Ansprüche des Nutzers enthält, muss der Server bei jeder Anfrage keinen Session-Zustand nachschlagen. Das macht JWTs gut geeignet für verteilte Systeme und Microservices.

Setze immer kurze Ablaufzeiten für Access-Token (z. B. 15 Minuten) und verwende Refresh-Token für das Erhalten neuer Access-Token. Speichere Refresh-Token sicher (httpOnly-Cookies, nicht localStorage) und implementiere Token-Rotation, sodass jedes Refresh-Token nur einmal verwendet werden kann.

Multi-Faktor-Authentifizierung (MFA)

Für Anwendungen mit sensiblen Daten ist MFA inzwischen Standard. Ein zweiter Faktor (TOTP-Codes, Hardware-Schlüssel oder Push-Benachrichtigungen) reduziert die Auswirkungen kompromittierter Passwörter erheblich. Selbst wenn ein Angreifer gültige Anmeldedaten erlangt, kann er sich ohne den zweiten Faktor nicht authentifizieren.

Session-Fixation verhindern

Session-Fixation-Angriffe treten auf, wenn ein Angreifer eine bekannte Session-ID setzt, bevor der Nutzer sich authentifiziert. Nach dem Login verwendet der Angreifer dieselbe Session-ID, um die authentifizierte Sitzung zu kapern. Verhindere dies, indem du die Session-ID nach erfolgreicher Authentifizierung immer regenerierst und die alte ungültig machst.

Sichere Session-Verwaltung

  • Erzeuge kryptografisch zufällige Session-IDs
  • Setze secure- und httpOnly-Flags auf Cookies
  • Implementiere Session-Timeout
  • Invalidiere Sitzungen beim Logout

Sicherheitsheader-Checkliste

HTTP-Response-Header gehören zu den einfachsten Maßnahmen zur Härtung deiner Anwendung. Schnellreferenz:

HeaderZweckBeispielwert
Content-Security-PolicyXSS und Daten-Injection verhinderndefault-src 'self'
Strict-Transport-SecurityHTTPS-Verbindungen erzwingenmax-age=31536000; includeSubDomains
X-Content-Type-OptionsMIME-Type-Sniffing verhindernnosniff
X-Frame-OptionsClickjacking verhindernDENY
Referrer-PolicyReferrer-Informationen kontrollierenstrict-origin-when-cross-origin

Diese Header können auf Webserver-Ebene (Nginx, Apache), auf CDN/Edge-Ebene (Cloudflare, Vercel) oder im Anwendungsframework gesetzt werden. Die meisten sind eine einzelne Zeile Konfiguration. Teste deine Header mit securityheaders.com.

Unsere Sicherheits-Tools nutzen

Siehe auch: MD5 Hash-Generator | UUID-Generator | Zufalls-Passwort-Generator | Entwickler-Werkzeuge

Häufig gestellte Fragen

Was ist die häufigste Web-Sicherheitslücke?

Cross-Site Scripting (XSS) bleibt laut OWASP die am weitesten verbreitete Web-Schwachstelle. Sie tritt auf, wenn Anwendungen nicht vertrauenswürdige Daten ohne korrekte Validierung in Webseiten einbinden. Verhindere XSS durch Bereinigung aller Nutzereingaben, Verwendung von Content-Security-Policy-Headern und kontextbezogenes Kodieren der Ausgabe (HTML, JavaScript, URL oder CSS).

Ist MD5 noch sicher für Passwort-Hashing?

Nein. MD5 sollte niemals für Passwort-Hashing verwendet werden. Es ist rechnerisch schnell und damit anfällig für Brute-Force- und Rainbow-Table-Angriffe. Moderne GPUs können Milliarden von MD5-Hashes pro Sekunde berechnen. Verwende stattdessen bcrypt, scrypt oder Argon2, die absichtlich langsam sind und eingebautes Salting bieten, um Angriffen zu widerstehen.

Wie lang sollte ein sicheres Passwort 2026 sein?

Mindestens 12 Zeichen werden empfohlen, aber 16+ Zeichen bieten deutlich stärkeren Schutz. Länge ist wichtiger als Komplexität. Eine 20-Zeichen-Passphrase wie „correct-horse-battery-staple” ist stärker als ein kurzes komplexes Passwort wie „P@ss1!”. Aktiviere Multi-Faktor-Authentifizierung (MFA) unabhängig von der Passwortlänge für kritische Konten.

Was ist der Unterschied zwischen Verschlüsselung und Hashing?

Verschlüsselung ist umkehrbar: Du kannst Daten mit einem Schlüssel zurück in die Originalform entschlüsseln. Hashing ist eine Einbahnstraße, du kannst die Originaldaten nicht aus einem Hash wiederherstellen. Verwende Verschlüsselung für Daten, die du abrufen musst (wie gespeicherte Nutzerdaten), und Hashing für Daten, die du nur verifizieren musst (wie Passwörter und Prüfsummen).

Sollte ich ein eigenes Authentifizierungssystem implementieren?

Nein. Authentifizierung von Grund auf zu bauen ist riskant und fehleranfällig. Verwende bewährte Frameworks und Dienste wie Auth0, Firebase Auth oder Supabase Auth. Diese handhaben Passwort-Hashing, Session-Verwaltung, Token-Rotation, MFA und Brute-Force-Schutz. Konzentriere deine Entwicklungszeit auf die einzigartigen Features deiner Anwendung.

Fazit

Die wichtigsten Maßnahmen mit dem besten Aufwand-Nutzen-Verhältnis: Passwörter mit bcrypt/Argon2 hashen, parametrisierte Abfragen verwenden, Sicherheitsheader setzen und MFA aktivieren. Damit sind die häufigsten Angriffsvektoren abgedeckt.

Verwandte Artikel

Alle Artikel anzeigen