En omfattende guide til bedste praksis for JWT (JSON Web Token) sikkerhed, der dækker validering, lagring, signeringsalgoritmer og strategier til at imødegå almindelige sårbarheder i internationale applikationer.
JWT Tokens: Bedste Praksis for Sikkerhed i Globale Applikationer
JSON Web Tokens (JWT'er) er blevet en standardmetode til sikkert at repræsentere claims mellem to parter. Deres kompakte struktur, brugervenlighed og brede understøttelse på tværs af forskellige platforme har gjort dem til et populært valg til autentificering og autorisation i moderne webapplikationer, API'er og microservices. Deres udbredte anvendelse har dog også ført til øget granskning og opdagelsen af talrige sikkerhedssårbarheder. Denne omfattende guide udforsker bedste praksis for JWT-sikkerhed for at sikre, at dine globale applikationer forbliver sikre og modstandsdygtige over for potentielle angreb.
Hvad er JWT'er, og hvordan fungerer de?
Et JWT er et JSON-baseret sikkerhedstoken, der består af tre dele:
- Header: Specificerer tokentypen (JWT) og den anvendte signeringsalgoritme (f.eks. HMAC SHA256 eller RSA).
- Payload: Indeholder claims, som er udsagn om en enhed (typisk brugeren) og yderligere metadata. Claims kan være registrerede (f.eks. udsteder, emne, udløbstidspunkt), offentlige (defineret af applikationen) eller private (brugerdefinerede claims).
- Signatur: Oprettes ved at kombinere den kodede header, den kodede payload, en hemmelig nøgle (for HMAC-algoritmer) eller en privat nøgle (for RSA/ECDSA-algoritmer), den specificerede algoritme og derefter signere resultatet.
Disse tre dele er Base64 URL-kodet og sammenkædet med punktummer (.
) for at danne den endelige JWT-streng. Når en bruger autentificerer sig, genererer serveren et JWT, som klienten derefter gemmer (typisk i local storage eller en cookie) og inkluderer i efterfølgende anmodninger. Serveren validerer derefter JWT'et for at autorisere anmodningen.
Forståelse af Almindelige JWT-sårbarheder
Før vi dykker ned i bedste praksis, er det afgørende at forstå de almindelige sårbarheder, der er forbundet med JWT'er:
- Algoritmeforvirring: Angribere udnytter muligheden for at ændre
alg
-parameteren i headeren fra en stærk asymmetrisk algoritme (som RSA) til en svag symmetrisk algoritme (som HMAC). Hvis serveren bruger den offentlige nøgle som den hemmelige nøgle i HMAC-algoritmen, kan angribere forfalske JWT'er. - Eksponering af hemmelig nøgle: Hvis den hemmelige nøgle, der bruges til at signere JWT'er, kompromitteres, kan angribere generere gyldige JWT'er og efterligne enhver bruger. Dette kan ske på grund af lækket kode, usikker lagring eller sårbarheder i andre dele af applikationen.
- Token-tyveri (XSS/CSRF): Hvis JWT'er opbevares usikkert, kan angribere stjæle dem gennem Cross-Site Scripting (XSS) eller Cross-Site Request Forgery (CSRF) angreb.
- Replay-angreb: Angribere kan genbruge gyldige JWT'er for at opnå uautoriseret adgang, især hvis tokens har en lang levetid, og der ikke er implementeret specifikke modforanstaltninger.
- Padding Oracle-angreb: Når JWT'er krypteres med visse algoritmer, og padding håndteres forkert, kan angribere potentielt dekryptere JWT'et og få adgang til dets indhold.
- Problemer med ur-afvigelse: I distribuerede systemer kan ur-afvigelser (clock skew) mellem forskellige servere føre til fejl i JWT-validering, især med udløbsclaims.
Bedste Praksis for JWT-sikkerhed
Her er omfattende bedste praksis for sikkerhed for at mindske risiciene forbundet med JWT'er:
1. Valg af den Rigtige Signeringsalgoritme
Valget af signeringsalgoritme er afgørende. Her er, hvad du skal overveje:
- Undgå
alg: none
: Tillad aldrig, atalg
-headeren sættes tilnone
. Dette deaktiverer signaturverifikation, hvilket tillader enhver at oprette gyldige JWT'er. Mange biblioteker er blevet patchet for at forhindre dette, men sørg for, at dine biblioteker er opdaterede. - Foretræk Asymmetriske Algoritmer (RSA/ECDSA): Brug RSA (RS256, RS384, RS512) eller ECDSA (ES256, ES384, ES512) algoritmer, når det er muligt. Asymmetriske algoritmer bruger en privat nøgle til signering og en offentlig nøgle til verifikation. Dette forhindrer angribere i at forfalske tokens, selvom de får adgang til den offentlige nøgle.
- Sikker Håndtering af Private Nøgler: Opbevar private nøgler sikkert ved hjælp af hardware security modules (HSM'er) eller sikre nøglehåndteringssystemer. Begå aldrig private nøgler til kildekodelagre.
- Roter Nøgler Regelmæssigt: Implementer en nøglerotationsstrategi for regelmæssigt at skifte signeringsnøgler. Dette minimerer virkningen, hvis en nøgle nogensinde kompromitteres. Overvej at bruge JSON Web Key Sets (JWKS) til at publicere dine offentlige nøgler.
Eksempel: Brug af JWKS til Nøglerotation
Et JWKS-endpoint leverer et sæt offentlige nøgler, der kan bruges til at verificere JWT'er. Serveren kan rotere nøgler, og klienter kan automatisk opdatere deres nøglesæt ved at hente JWKS-endpointet.
/.well-known/jwks.json
:
{
"keys": [
{
"kty": "RSA",
"kid": "key1",
"alg": "RS256",
"n": "...",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "key2",
"alg": "RS256",
"n": "...",
"e": "AQAB"
}
]
}
2. Korrekt Validering af JWT'er
Korrekt validering er afgørende for at forhindre angreb:
- Verificer Signaturen: Verificer altid JWT-signaturen ved hjælp af den korrekte nøgle og algoritme. Sørg for, at dit JWT-bibliotek er korrekt konfigureret og opdateret.
- Valider Claims: Valider essentielle claims som
exp
(udløbstid),nbf
(ikke før),iss
(udsteder) ogaud
(målgruppe). - Tjek
exp
Claim: Sørg for, at JWT'et ikke er udløbet. Implementer en fornuftig token-levetid for at minimere tidsvinduet for angribere. - Tjek
nbf
Claim: Sørg for, at JWT'et ikke bruges før dets gyldige starttidspunkt. Dette forhindrer replay-angreb, før tokenet er beregnet til at blive brugt. - Tjek
iss
Claim: Verificer, at JWT'et blev udstedt af en betroet udsteder. Dette forhindrer angribere i at bruge JWT'er udstedt af uautoriserede parter. - Tjek
aud
Claim: Verificer, at JWT'et er beregnet til din applikation. Dette forhindrer, at JWT'er udstedt til andre applikationer bliver brugt mod din. - Implementer en Afvisningsliste (Valgfrit): For kritiske applikationer kan du overveje at implementere en afvisningsliste (også kendt som en tilbagekaldelsesliste) for at ugyldiggøre kompromitterede JWT'er før deres udløbstid. Dette tilføjer kompleksitet, men kan forbedre sikkerheden betydeligt.
Eksempel: Validering af Claims i Kode (Node.js med 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 validering mislykkedes:', error);
}
3. Sikker Opbevaring af JWT'er på Klientsiden
Hvordan JWT'er opbevares på klientsiden har en betydelig indvirkning på sikkerheden:
- Undgå Local Storage: Opbevaring af JWT'er i local storage gør dem sårbare over for XSS-angreb. Hvis en angriber kan injicere JavaScript i din applikation, kan de let stjæle JWT'et fra local storage.
- Brug HTTP-Only Cookies: Opbevar JWT'er i HTTP-only cookies med attributterne
Secure
ogSameSite
. HTTP-only cookies kan ikke tilgås af JavaScript, hvilket mindsker XSS-risici.Secure
-attributten sikrer, at cookien kun sendes over HTTPS.SameSite
-attributten hjælper med at forhindre CSRF-angreb. - Overvej Refresh Tokens: Implementer en refresh token-mekanisme. Kortlivede adgangstokens bruges til øjeblikkelig autorisation, mens langlevede refresh tokens bruges til at få nye adgangstokens. Opbevar refresh tokens sikkert (f.eks. i en database med kryptering).
- Implementer CSRF-beskyttelse: Når du bruger cookies, skal du implementere CSRF-beskyttelsesmekanismer, såsom synchronizer tokens eller Double Submit Cookie-mønsteret.
Eksempel: Indstilling af HTTP-Only Cookies (Node.js med Express)
app.get('/login', (req, res) => {
// ... autentificeringslogik ...
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, // Sættes til true i produktion
sameSite: 'strict', // eller 'lax' afhængigt af dine behov
maxAge: 15 * 60 * 1000 // 15 minutter
});
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true, // Sættes til true i produktion
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 dage
});
res.send({ message: 'Login succesfuldt' });
});
4. Beskyttelse mod Algoritmeforvirringsangreb
Algoritmeforvirring er en kritisk sårbarhed. Sådan forhindrer du det:
- Specificer Eksplicit Tilladte Algoritmer: Når du verificerer JWT'er, skal du eksplicit specificere de tilladte signeringsalgoritmer. Stol ikke på, at JWT-biblioteket automatisk bestemmer algoritmen.
- Stol Ikke på
alg
-headeren: Stol aldrig blindt påalg
-headeren i JWT'et. Valider den altid mod en foruddefineret liste over tilladte algoritmer. - Brug Stærk Statisk Typning (hvis muligt): I sprog, der understøtter statisk typning, skal du håndhæve streng typekontrol for nøgle- og algoritmeparametrene.
Eksempel: Forebyggelse af Algoritmeforvirring (Node.js med jsonwebtoken
)
const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'] // Tillad eksplicit kun RS256
});
console.log(decoded);
} catch (error) {
console.error('JWT validering mislykkedes:', error);
}
5. Implementering af Korrekt Tokenudløb og Opdateringsmekanismer
Tokenets levetid er en central sikkerhedsovervejelse:
- Brug Kortlivede Adgangstokens: Hold adgangstokens kortlivede (f.eks. 5-30 minutter). Dette begrænser virkningen, hvis et token kompromitteres.
- Implementer Refresh Tokens: Brug refresh tokens til at opnå nye adgangstokens uden at kræve, at brugeren genautentificerer sig. Refresh tokens kan have en længere levetid, men skal opbevares sikkert.
- Implementer Refresh Token-rotation: Roter refresh tokens, hver gang et nyt adgangstoken udstedes. Dette ugyldiggør det gamle refresh token, hvilket begrænser den potentielle skade, hvis et refresh token kompromitteres.
- Overvej Sessionsstyring: For følsomme applikationer kan du overveje at implementere server-side sessionsstyring ud over JWT'er. Dette giver dig mulighed for at tilbagekalde adgang mere granulært.
6. Beskyttelse mod Token-tyveri
Forebyggelse af token-tyveri er afgørende:
- Implementer Streng Content Security Policy (CSP): Brug CSP til at forhindre XSS-angreb. CSP giver dig mulighed for at specificere, hvilke kilder der må indlæse ressourcer (scripts, styles, billeder osv.) på dit websted.
- Rens Brugerinput: Rens alt brugerinput for at forhindre XSS-angreb. Brug et betroet HTML-rensningsbibliotek til at escape potentielt ondsindede tegn.
- Brug HTTPS: Brug altid HTTPS til at kryptere kommunikationen mellem klienten og serveren. Dette forhindrer angribere i at aflytte netværkstrafik og stjæle JWT'er.
- Implementer HSTS (HTTP Strict Transport Security): Brug HSTS til at instruere browsere til altid at bruge HTTPS, når de kommunikerer med dit websted.
7. Overvågning og Logning
Effektiv overvågning og logning er afgørende for at opdage og reagere på sikkerhedshændelser:
- Log Udstedelse og Validering af JWT: Log alle hændelser vedrørende udstedelse og validering af JWT, herunder bruger-ID, IP-adresse og tidsstempel.
- Overvåg for Mistænkelig Aktivitet: Overvåg for usædvanlige mønstre, såsom flere mislykkede loginforsøg, JWT'er, der bruges fra forskellige steder samtidigt, eller hurtige anmodninger om token-opdatering.
- Opsæt Alarmer: Opsæt alarmer for at underrette dig om potentielle sikkerhedshændelser.
- Gennemgå Logs Regelmæssigt: Gennemgå logs regelmæssigt for at identificere og undersøge mistænkelig aktivitet.
8. Rate Limiting
Implementer rate limiting for at forhindre brute-force-angreb og denial-of-service (DoS) angreb:
- Begræns Loginforsøg: Begræns antallet af mislykkede loginforsøg fra en enkelt IP-adresse eller brugerkonto.
- Begræns Anmodninger om Token-opdatering: Begræns antallet af anmodninger om token-opdatering fra en enkelt IP-adresse eller brugerkonto.
- Begræns API-anmodninger: Begræns antallet af API-anmodninger fra en enkelt IP-adresse eller brugerkonto.
9. Hold dig Opdateret
- Hold Biblioteker Opdaterede: Opdater regelmæssigt dine JWT-biblioteker og afhængigheder for at patche sikkerhedssårbarheder.
- Følg Bedste Sikkerhedspraksis: Hold dig informeret om de seneste bedste sikkerhedspraksis og sårbarheder relateret til JWT'er.
- Udfør Sikkerhedsrevisioner: Udfør regelmæssigt sikkerhedsrevisioner af din applikation for at identificere og adressere potentielle sårbarheder.
Globale Overvejelser for JWT-sikkerhed
Når du implementerer JWT'er til globale applikationer, skal du overveje følgende:
- Tidszoner: Sørg for, at dine servere er synkroniseret til en pålidelig tidskilde (f.eks. NTP) for at undgå problemer med ur-afvigelser, der kan påvirke JWT-validering, især
exp
ognbf
claims. Overvej at bruge UTC-tidsstempler konsekvent. - Databeskyttelsesregler: Vær opmærksom på databeskyttelsesregler som GDPR, CCPA og andre. Minimer mængden af personlige data, der gemmes i JWT'er, og sørg for overholdelse af relevante regler. Krypter følsomme claims om nødvendigt.
- Internationalisering (i18n): Når du viser oplysninger fra JWT-claims, skal du sikre, at dataene er korrekt lokaliseret til brugerens sprog og region. Dette inkluderer formatering af datoer, tal og valutaer korrekt.
- Juridisk Overholdelse: Vær opmærksom på eventuelle juridiske krav relateret til datalagring og -transmission i forskellige lande. Sørg for, at din JWT-implementering overholder alle gældende love og regler.
- Cross-Origin Resource Sharing (CORS): Konfigurer CORS korrekt for at tillade din applikation at få adgang til ressourcer fra forskellige domæner. Dette er især vigtigt, når du bruger JWT'er til autentificering på tværs af forskellige tjenester eller applikationer.
Konklusion
JWT'er tilbyder en bekvem og effektiv måde at håndtere autentificering og autorisation på, men de introducerer også potentielle sikkerhedsrisici. Ved at følge disse bedste praksisser kan du markant reducere risikoen for sårbarheder og sikre sikkerheden i dine globale applikationer. Husk at holde dig informeret om de seneste sikkerhedstrusler og opdatere din implementering i overensstemmelse hermed. At prioritere sikkerhed gennem hele JWT-livscyklussen vil hjælpe med at beskytte dine brugere og data mod uautoriseret adgang.