Ein umfassender Leitfaden zu JWT (JSON Web Token) Sicherheits-Best Practices, inklusive Validierung, Speicherung, Signaturalgorithmen und Strategien zur Minderung von Sicherheitslücken.
JWT-Tokens: Sicherheits-Best Practices für globale Anwendungen
JSON Web Tokens (JWTs) haben sich zu einer Standardmethode entwickelt, um Ansprüche zwischen zwei Parteien sicher darzustellen. Ihre kompakte Struktur, die einfache Verwendung und die breite Unterstützung auf verschiedenen Plattformen haben sie zu einer beliebten Wahl für die Authentifizierung und Autorisierung in modernen Webanwendungen, APIs und Microservices gemacht. Ihre weitverbreitete Akzeptanz hat jedoch auch zu einer verstärkten Prüfung und der Entdeckung zahlreicher Sicherheitslücken geführt. Dieser umfassende Leitfaden untersucht die JWT-Sicherheits-Best Practices, um sicherzustellen, dass Ihre globalen Anwendungen sicher und widerstandsfähig gegen potenzielle Angriffe bleiben.
Was sind JWTs und wie funktionieren sie?
Ein JWT ist ein JSON-basiertes Sicherheitstoken, das aus drei Teilen besteht:
- Header: Gibt den Typ des Tokens (JWT) und den verwendeten Signaturalgorithmus an (z. B. HMAC SHA256 oder RSA).
- Payload: Enthält Ansprüche, d. h. Aussagen über eine Entität (typischerweise den Benutzer) und zusätzliche Metadaten. Ansprüche können registriert (z. B. Aussteller, Subjekt, Ablaufzeit), öffentlich (von der Anwendung definiert) oder privat (benutzerdefinierte Ansprüche) sein.
- Signatur: Wird erstellt, indem der kodierte Header, die kodierte Payload, ein geheimer Schlüssel (für HMAC-Algorithmen) oder ein privater Schlüssel (für RSA/ECDSA-Algorithmen), der angegebene Algorithmus und die Signierung des Ergebnisses kombiniert werden.
Diese drei Teile werden Base64 URL-kodiert und mit Punkten (.
) verkettet, um die endgültige JWT-Zeichenfolge zu bilden. Wenn sich ein Benutzer authentifiziert, generiert der Server ein JWT, das der Client dann speichert (typischerweise im lokalen Speicher oder in einem Cookie) und in nachfolgenden Anfragen einfügt. Der Server validiert dann das JWT, um die Anfrage zu autorisieren.
Verständnis gängiger JWT-Sicherheitslücken
Bevor wir uns mit den Best Practices befassen, ist es wichtig, die gängigen Sicherheitslücken im Zusammenhang mit JWTs zu verstehen:
- Algorithmusverwirrung: Angreifer nutzen die Möglichkeit, den
alg
-Header-Parameter von einem starken asymmetrischen Algorithmus (wie RSA) in einen schwachen symmetrischen Algorithmus (wie HMAC) zu ändern. Wenn der Server den öffentlichen Schlüssel als geheimen Schlüssel im HMAC-Algorithmus verwendet, können Angreifer JWTs fälschen. - Offenlegung des geheimen Schlüssels: Wenn der geheime Schlüssel, der zum Signieren von JWTs verwendet wird, kompromittiert wird, können Angreifer gültige JWTs generieren und sich als beliebiger Benutzer ausgeben. Dies kann aufgrund von Codelecks, unsicherer Speicherung oder Sicherheitslücken in anderen Teilen der Anwendung geschehen.
- Token-Diebstahl (XSS/CSRF): Wenn JWTs unsicher gespeichert werden, können Angreifer sie durch Cross-Site Scripting (XSS) oder Cross-Site Request Forgery (CSRF)-Angriffe stehlen.
- Replay-Angriffe: Angreifer können gültige JWTs wiederverwenden, um unbefugten Zugriff zu erhalten, insbesondere wenn die Token eine lange Lebensdauer haben und keine spezifischen Gegenmaßnahmen implementiert sind.
- Padding-Oracle-Angriffe: Wenn JWTs mit bestimmten Algorithmen verschlüsselt werden und Padding falsch behandelt wird, können Angreifer das JWT möglicherweise entschlüsseln und auf dessen Inhalt zugreifen.
- Uhrzeitabweichungen: In verteilten Systemen können Uhrzeitabweichungen zwischen verschiedenen Servern zu Fehlern bei der JWT-Validierung führen, insbesondere bei Ablaufansprüchen.
JWT Sicherheits-Best Practices
Hier sind umfassende Sicherheits-Best Practices, um die mit JWTs verbundenen Risiken zu mindern:
1. Auswahl des richtigen Signaturalgorithmus
Die Wahl des Signaturalgorithmus ist entscheidend. Hier ist, was zu beachten ist:
- Vermeiden Sie
alg: none
: Erlauben Sie niemals, dass deralg
-Header aufnone
gesetzt wird. Dies deaktiviert die Signaturüberprüfung, so dass jeder gültige JWTs erstellen kann. Viele Bibliotheken wurden gepatcht, um dies zu verhindern, aber stellen Sie sicher, dass Ihre Bibliotheken auf dem neuesten Stand sind. - Bevorzugen Sie asymmetrische Algorithmen (RSA/ECDSA): Verwenden Sie nach Möglichkeit RSA (RS256, RS384, RS512) oder ECDSA (ES256, ES384, ES512) Algorithmen. Asymmetrische Algorithmen verwenden einen privaten Schlüssel zum Signieren und einen öffentlichen Schlüssel zur Überprüfung. Dies verhindert, dass Angreifer Token fälschen können, selbst wenn sie Zugriff auf den öffentlichen Schlüssel erhalten.
- Verwalten Sie private Schlüssel sicher: Speichern Sie private Schlüssel sicher mit Hardware-Sicherheitsmodulen (HSMs) oder sicheren Schlüsselverwaltungssystemen. Übertragen Sie niemals private Schlüssel an Quellcode-Repositories.
- Rotieren Sie Schlüssel regelmäßig: Implementieren Sie eine Schlüsselrotationsstrategie, um die Signierschlüssel regelmäßig zu ändern. Dies minimiert die Auswirkungen, wenn ein Schlüssel jemals kompromittiert wird. Erwägen Sie die Verwendung von JSON Web Key Sets (JWKS), um Ihre öffentlichen Schlüssel zu veröffentlichen.
Beispiel: Verwenden von JWKS für die Schlüsselrotation
Ein JWKS-Endpunkt bietet eine Reihe von öffentlichen Schlüsseln, die zum Überprüfen von JWTs verwendet werden können. Der Server kann Schlüssel rotieren, und Clients können ihren Schlüsselsatz automatisch aktualisieren, indem sie den JWKS-Endpunkt abrufen.
/.well-known/jwks.json
:
{
"keys": [
{
"kty": "RSA",
"kid": "key1",
"alg": "RS256",
"n": "...",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "key2",
"alg": "RS256",
"n": "...",
"e": "AQAB"
}
]
}
2. Validierung von JWTs ordnungsgemäß
Die ordnungsgemäße Validierung ist unerlässlich, um Angriffe zu verhindern:
- Überprüfen Sie die Signatur: Überprüfen Sie immer die JWT-Signatur mit dem richtigen Schlüssel und Algorithmus. Stellen Sie sicher, dass Ihre JWT-Bibliothek korrekt konfiguriert und auf dem neuesten Stand ist.
- Validieren Sie Ansprüche: Validieren Sie wesentliche Ansprüche wie
exp
(Ablaufzeit),nbf
(nicht vor),iss
(Aussteller) undaud
(Zielgruppe). - Überprüfen Sie den
exp
-Anspruch: Stellen Sie sicher, dass das JWT nicht abgelaufen ist. Implementieren Sie eine angemessene Token-Lebensdauer, um das Zeitfenster für Angreifer zu minimieren. - Überprüfen Sie den
nbf
-Anspruch: Stellen Sie sicher, dass das JWT nicht vor seiner gültigen Startzeit verwendet wird. Dies verhindert Replay-Angriffe, bevor das Token verwendet werden soll. - Überprüfen Sie den
iss
-Anspruch: Überprüfen Sie, ob das JWT von einem vertrauenswürdigen Aussteller ausgestellt wurde. Dies verhindert, dass Angreifer JWTs verwenden, die von nicht autorisierten Parteien ausgestellt wurden. - Überprüfen Sie den
aud
-Anspruch: Überprüfen Sie, ob das JWT für Ihre Anwendung bestimmt ist. Dies verhindert, dass JWTs, die für andere Anwendungen ausgestellt wurden, gegen Ihre verwendet werden. - Implementieren Sie eine Ablehnungsliste (Optional): Für kritische Anwendungen sollten Sie die Implementierung einer Ablehnungsliste (auch bekannt als Widerrufsliste) in Betracht ziehen, um kompromittierte JWTs vor ihrer Ablaufzeit ungültig zu machen. Dies erhöht die Komplexität, kann aber die Sicherheit erheblich verbessern.
Beispiel: Validieren von Ansprüchen im Code (Node.js mit jsonwebtoken
)
const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
issuer: 'https://example.com',
audience: 'https://myapp.com'
});
console.log(decoded);
} catch (error) {
console.error('JWT validation failed:', error);
}
3. Sichere Speicherung von JWTs auf der Client-Seite
Wie JWTs auf der Client-Seite gespeichert werden, hat erhebliche Auswirkungen auf die Sicherheit:
- Vermeiden Sie Local Storage: Das Speichern von JWTs im Local Storage macht sie anfällig für XSS-Angriffe. Wenn ein Angreifer JavaScript in Ihre Anwendung einschleusen kann, kann er das JWT problemlos aus dem Local Storage stehlen.
- Verwenden Sie HTTP-Only Cookies: Speichern Sie JWTs in HTTP-Only Cookies mit den Attributen
Secure
undSameSite
. HTTP-Only Cookies können nicht von JavaScript abgerufen werden, wodurch XSS-Risiken gemindert werden. Das AttributSecure
stellt sicher, dass das Cookie nur über HTTPS übertragen wird. Das AttributSameSite
hilft, CSRF-Angriffe zu verhindern. - Erwägen Sie Refresh-Token: Implementieren Sie einen Refresh-Token-Mechanismus. Kurzlebige Zugriffstoken werden für die sofortige Autorisierung verwendet, während langlebige Refresh-Token verwendet werden, um neue Zugriffstoken zu erhalten. Speichern Sie Refresh-Token sicher (z. B. in einer Datenbank mit Verschlüsselung).
- Implementieren Sie CSRF-Schutz: Wenn Sie Cookies verwenden, implementieren Sie CSRF-Schutzmechanismen, wie z. B. Synchronizer-Token oder das Double Submit Cookie-Muster.
Beispiel: Festlegen von HTTP-Only Cookies (Node.js mit Express)
app.get('/login', (req, res) => {
// ... authentication logic ...
const token = jwt.sign({ userId: user.id }, privateKey, { expiresIn: '15m' });
const refreshToken = jwt.sign({ userId: user.id }, refreshPrivateKey, { expiresIn: '7d' });
res.cookie('accessToken', token, {
httpOnly: true,
secure: true, // Auf "true" in der Produktion setzen
sameSite: 'strict', // oder 'lax' je nach Ihren Bedürfnissen
maxAge: 15 * 60 * 1000 // 15 Minuten
});
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true, // Auf "true" in der Produktion setzen
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 Tage
});
res.send({ message: 'Login successful' });
});
4. Schutz vor Algorithmusverwirrungsangriffen
Algorithmusverwirrung ist eine kritische Sicherheitslücke. So verhindern Sie sie:
- Geben Sie explizit zulässige Algorithmen an: Geben Sie beim Überprüfen von JWTs explizit die zulässigen Signaturalgorithmen an. Verlassen Sie sich nicht darauf, dass die JWT-Bibliothek den Algorithmus automatisch bestimmt.
- Vertrauen Sie dem
alg
-Header nicht: Vertrauen Sie niemals blind demalg
-Header im JWT. Validieren Sie ihn immer anhand einer vordefinierten Liste zulässiger Algorithmen. - Verwenden Sie eine starke statische Typisierung (wenn möglich): Erzwingen Sie in Sprachen, die die statische Typisierung unterstützen, eine strenge Typüberprüfung für die Schlüssel- und Algorithmusparameter.
Beispiel: Verhindern von Algorithmusverwirrung (Node.js mit jsonwebtoken
)
const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'] // Erlauben Sie explizit nur RS256
});
console.log(decoded);
} catch (error) {
console.error('JWT validation failed:', error);
}
5. Implementierung geeigneter Token-Ablauf- und Aktualisierungsmechanismen
Die Token-Lebensdauer ist eine wichtige Sicherheitsüberlegung:
- Verwenden Sie kurzlebige Zugriffstoken: Halten Sie Zugriffstoken kurzlebig (z. B. 5-30 Minuten). Dies begrenzt die Auswirkungen, wenn ein Token kompromittiert wird.
- Implementieren Sie Refresh-Token: Verwenden Sie Refresh-Token, um neue Zugriffstoken zu erhalten, ohne dass sich der Benutzer erneut authentifizieren muss. Refresh-Token können eine längere Lebensdauer haben, sollten aber sicher gespeichert werden.
- Implementieren Sie die Rotation von Refresh-Token: Rotieren Sie Refresh-Token jedes Mal, wenn ein neues Zugriffstoken ausgestellt wird. Dies macht das alte Refresh-Token ungültig und begrenzt den potenziellen Schaden, wenn ein Refresh-Token kompromittiert wird.
- Erwägen Sie die Sitzungsverwaltung: Für sensible Anwendungen sollten Sie die Implementierung einer serverseitigen Sitzungsverwaltung zusätzlich zu JWTs in Betracht ziehen. Dies ermöglicht es Ihnen, den Zugriff detaillierter zu widerrufen.
6. Schutz vor Token-Diebstahl
Die Verhinderung von Token-Diebstahl ist entscheidend:
- Implementieren Sie eine strenge Content Security Policy (CSP): Verwenden Sie CSP, um XSS-Angriffe zu verhindern. Mit CSP können Sie angeben, welche Quellen Ressourcen (Skripte, Stile, Bilder usw.) auf Ihrer Website laden dürfen.
- Bereinigen Sie Benutzereingaben: Bereinigen Sie alle Benutzereingaben, um XSS-Angriffe zu verhindern. Verwenden Sie eine vertrauenswürdige HTML-Sanitizer-Bibliothek, um potenziell schädliche Zeichen zu maskieren.
- Verwenden Sie HTTPS: Verwenden Sie immer HTTPS, um die Kommunikation zwischen dem Client und dem Server zu verschlüsseln. Dies verhindert, dass Angreifer den Netzwerkverkehr abhören und JWTs stehlen.
- Implementieren Sie HSTS (HTTP Strict Transport Security): Verwenden Sie HSTS, um Browser anzuweisen, immer HTTPS zu verwenden, wenn sie mit Ihrer Website kommunizieren.
7. Überwachung und Protokollierung
Eine effektive Überwachung und Protokollierung sind unerlässlich, um Sicherheitsvorfälle zu erkennen und darauf zu reagieren:
- Protokollieren Sie die JWT-Ausstellung und -Validierung: Protokollieren Sie alle JWT-Ausstellungs- und Validierungsereignisse, einschließlich der Benutzer-ID, IP-Adresse und des Zeitstempels.
- Überwachen Sie auf verdächtige Aktivitäten: Überwachen Sie auf ungewöhnliche Muster, wie z. B. mehrere fehlgeschlagene Anmeldeversuche, JWTs, die gleichzeitig von verschiedenen Standorten aus verwendet werden, oder schnelle Token-Aktualisierungsanforderungen.
- Richten Sie Warnungen ein: Richten Sie Warnungen ein, um Sie über potenzielle Sicherheitsvorfälle zu informieren.
- Überprüfen Sie regelmäßig die Protokolle: Überprüfen Sie regelmäßig die Protokolle, um verdächtige Aktivitäten zu identifizieren und zu untersuchen.
8. Ratenbegrenzung
Implementieren Sie eine Ratenbegrenzung, um Brute-Force-Angriffe und Denial-of-Service (DoS)-Angriffe zu verhindern:
- Begrenzen Sie Anmeldeversuche: Begrenzen Sie die Anzahl der fehlgeschlagenen Anmeldeversuche von einer einzelnen IP-Adresse oder einem Benutzerkonto.
- Begrenzen Sie Token-Aktualisierungsanforderungen: Begrenzen Sie die Anzahl der Token-Aktualisierungsanforderungen von einer einzelnen IP-Adresse oder einem Benutzerkonto.
- Begrenzen Sie API-Anforderungen: Begrenzen Sie die Anzahl der API-Anforderungen von einer einzelnen IP-Adresse oder einem Benutzerkonto.
9. Auf dem Laufenden bleiben
- Halten Sie Bibliotheken auf dem neuesten Stand: Aktualisieren Sie regelmäßig Ihre JWT-Bibliotheken und Abhängigkeiten, um Sicherheitslücken zu patchen.
- Befolgen Sie die Sicherheits-Best Practices: Bleiben Sie über die neuesten Sicherheits-Best Practices und Sicherheitslücken im Zusammenhang mit JWTs informiert.
- Führen Sie Sicherheitsaudits durch: Führen Sie regelmäßig Sicherheitsaudits Ihrer Anwendung durch, um potenzielle Sicherheitslücken zu identifizieren und zu beheben.
Globale Überlegungen zur JWT-Sicherheit
Beachten Sie bei der Implementierung von JWTs für globale Anwendungen Folgendes:
- Zeitzonen: Stellen Sie sicher, dass Ihre Server mit einer zuverlässigen Zeitquelle (z. B. NTP) synchronisiert sind, um Uhrzeitabweichungen zu vermeiden, die sich auf die JWT-Validierung auswirken können, insbesondere die Ansprüche
exp
undnbf
. Erwägen Sie die konsistente Verwendung von UTC-Zeitstempeln. - Datenschutzbestimmungen: Beachten Sie die Datenschutzbestimmungen wie DSGVO, CCPA und andere. Minimieren Sie die Menge an personenbezogenen Daten, die in JWTs gespeichert werden, und stellen Sie die Einhaltung der einschlägigen Vorschriften sicher. Verschlüsseln Sie bei Bedarf sensible Ansprüche.
- Internationalisierung (i18n): Stellen Sie bei der Anzeige von Informationen aus JWT-Ansprüchen sicher, dass die Daten ordnungsgemäß für die Sprache und Region des Benutzers lokalisiert sind. Dies umfasst die entsprechende Formatierung von Datumsangaben, Zahlen und Währungen.
- Gesetzliche Bestimmungen: Beachten Sie alle gesetzlichen Anforderungen in Bezug auf Datenspeicherung und -übertragung in verschiedenen Ländern. Stellen Sie sicher, dass Ihre JWT-Implementierung allen geltenden Gesetzen und Vorschriften entspricht.
- Cross-Origin Resource Sharing (CORS): Konfigurieren Sie CORS ordnungsgemäß, damit Ihre Anwendung auf Ressourcen aus verschiedenen Domänen zugreifen kann. Dies ist besonders wichtig, wenn JWTs für die Authentifizierung über verschiedene Dienste oder Anwendungen hinweg verwendet werden.
Fazit
JWTs bieten eine bequeme und effiziente Möglichkeit, Authentifizierung und Autorisierung zu verarbeiten, bergen aber auch potenzielle Sicherheitsrisiken. Durch die Einhaltung dieser Best Practices können Sie das Risiko von Sicherheitslücken erheblich reduzieren und die Sicherheit Ihrer globalen Anwendungen gewährleisten. Denken Sie daran, sich über die neuesten Sicherheitsbedrohungen auf dem Laufenden zu halten und Ihre Implementierung entsprechend zu aktualisieren. Die Priorisierung der Sicherheit während des gesamten JWT-Lebenszyklus trägt dazu bei, Ihre Benutzer und Daten vor unbefugtem Zugriff zu schützen.