Išsamus JWT saugumo vadovas: patvirtinimas, saugojimas, pasirašymo algoritmai ir apsauga nuo pažeidžiamumų tarptautinėse programose.
JWT prieigos raktai: Saugumo geriausios praktikos globalioms programoms
JSON žiniatinklio prieigos raktai (angl. JSON Web Tokens, JWT) tapo standartiniu metodu saugiai pateikti pareiškimus (angl. claims) tarp dviejų šalių. Jų kompaktiška struktūra, paprastas naudojimas ir platus palaikymas įvairiose platformose pavertė juos populiariu pasirinkimu autentifikacijai ir autorizacijai moderniose žiniatinklio programose, API ir mikroservisuose. Tačiau jų plačiai paplitęs naudojimas taip pat lėmė padidėjusį dėmesį ir daugybės saugumo pažeidžiamumų atradimą. Šis išsamus vadovas nagrinėja JWT saugumo geriausias praktikas, siekiant užtikrinti, kad jūsų globalios programos išliktų saugios ir atsparios galimoms atakoms.
Kas yra JWT ir kaip jie veikia?
JWT yra JSON pagrindu sukurtas saugumo prieigos raktas, sudarytas iš trijų dalių:
- Antraštė (Header): Nurodo prieigos rakto tipą (JWT) ir naudojamą pasirašymo algoritmą (pvz., HMAC SHA256 arba RSA).
- Naudingoji dalis (Payload): Sudėtyje yra pareiškimai (angl. claims), kurie yra teiginiai apie subjektą (paprastai vartotoją) ir papildomi metaduomenys. Pareiškimai gali būti registruoti (pvz., leidėjas, subjektas, galiojimo laikas), vieši (apibrėžti programos) arba privatūs (individualūs pareiškimai).
- Parašas (Signature): Sukuriamas sujungiant užkoduotą antraštę, užkoduotą naudingąją dalį, slaptąjį raktą (HMAC algoritmams) arba privatųjį raktą (RSA/ECDSA algoritmams), nurodytą algoritmą ir pasirašant rezultatą.
Šios trys dalys yra užkoduojamos Base64 URL formatu ir sujungiamos taškais (.
), kad sudarytų galutinę JWT eilutę. Kai vartotojas autentifikuojasi, serveris sugeneruoja JWT, kurį klientas išsaugo (paprastai vietinėje saugykloje arba slapuke) ir įtraukia į vėlesnes užklausas. Tuomet serveris patvirtina JWT, kad autorizuotų užklausą.
Dažniausių JWT pažeidžiamumų supratimas
Prieš gilinantis į geriausias praktikas, svarbu suprasti dažniausius su JWT susijusius pažeidžiamumus:
- Algoritmų painiava: Užpuolikai išnaudoja galimybę pakeisti
alg
antraštės parametrą iš stipraus asimetrinio algoritmo (pvz., RSA) į silpną simetrinį algoritmą (pvz., HMAC). Jei serveris naudoja viešąjį raktą kaip slaptąjį raktą HMAC algoritme, užpuolikai gali suklastoti JWT. - Slaptojo rakto atskleidimas: Jei JWT pasirašymui naudojamas slaptasis raktas yra kompromituotas, užpuolikai gali generuoti galiojančius JWT, apsimesdami bet kuriuo vartotoju. Tai gali nutikti dėl kodo nutekėjimo, nesaugaus saugojimo ar pažeidžiamumų kitose programos dalyse.
- Prieigos rakto vagystė (XSS/CSRF): Jei JWT yra saugomi nesaugiai, užpuolikai gali juos pavogti per „Cross-Site Scripting“ (XSS) arba „Cross-Site Request Forgery“ (CSRF) atakas.
- Pakartojimo atakos: Užpuolikai gali pakartotinai naudoti galiojančius JWT, kad gautų neautorizuotą prieigą, ypač jei prieigos raktai turi ilgą galiojimo laiką ir nėra įdiegtų jokių specifinių apsaugos priemonių.
- Užpildo orakulo atakos (Padding Oracle Attacks): Kai JWT yra šifruojami tam tikrais algoritmais ir užpildas (angl. padding) tvarkomas neteisingai, užpuolikai potencialiai gali iššifruoti JWT ir pasiekti jo turinį.
- Laikrodžio sinchronizavimo problemos: Paskirstytose sistemose laikrodžių sinchronizavimo neatitikimai tarp skirtingų serverių gali sukelti JWT patvirtinimo klaidas, ypač su galiojimo pabaigos pareiškimais.
JWT saugumo geriausios praktikos
Štai išsamios saugumo geriausios praktikos, skirtos sumažinti su JWT susijusias rizikas:
1. Tinkamo pasirašymo algoritmo pasirinkimas
Pasirašymo algoritmo pasirinkimas yra kritiškai svarbus. Štai ką reikia apsvarstyti:
- Venkite
alg: none
: Niekada neleiskite, kadalg
antraštė būtų nustatyta įnone
. Tai išjungia parašo patikrinimą, leisdama bet kam sukurti galiojančius JWT. Dauguma bibliotekų buvo pataisytos, kad to išvengtų, tačiau įsitikinkite, kad jūsų bibliotekos yra atnaujintos. - Teikite pirmenybę asimetriniams algoritmams (RSA/ECDSA): Kai tik įmanoma, naudokite RSA (RS256, RS384, RS512) arba ECDSA (ES256, ES384, ES512) algoritmus. Asimetriniai algoritmai naudoja privatųjį raktą pasirašymui ir viešąjį raktą patikrinimui. Tai neleidžia užpuolikams klastoti prieigos raktų, net jei jie gauna prieigą prie viešojo rakto.
- Saugiai valdykite privačius raktus: Saugokite privačius raktus saugiai, naudodami aparatinės įrangos saugumo modulius (HSM) arba saugias raktų valdymo sistemas. Niekada neįkelkite privačių raktų į kodo saugyklas.
- Reguliariai keiskite raktus: Įdiekite raktų keitimo (rotacijos) strategiją, kad reguliariai keistumėte pasirašymo raktus. Tai sumažina poveikį, jei raktas kada nors būtų kompromituotas. Apsvarstykite galimybę naudoti JSON žiniatinklio raktų rinkinius (JWKS) savo viešiesiems raktams skelbti.
Pavyzdys: JWKS naudojimas raktų rotacijai
JWKS galinis punktas pateikia viešųjų raktų rinkinį, kuris gali būti naudojamas JWT patvirtinimui. Serveris gali keisti raktus, o klientai gali automatiškai atnaujinti savo raktų rinkinį, pasiekdami JWKS galinį punktą.
/.well-known/jwks.json
:
{
"keys": [
{
"kty": "RSA",
"kid": "key1",
"alg": "RS256",
"n": "...",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "key2",
"alg": "RS256",
"n": "...",
"e": "AQAB"
}
]
}
2. Tinkamas JWT patvirtinimas
Tinkamas patvirtinimas yra būtinas siekiant išvengti atakų:
- Patikrinkite parašą: Visada patikrinkite JWT parašą naudodami teisingą raktą ir algoritmą. Įsitikinkite, kad jūsų JWT biblioteka yra teisingai sukonfigūruota ir atnaujinta.
- Patvirtinkite pareiškimus: Patvirtinkite esminius pareiškimus, tokius kaip
exp
(galiojimo pabaigos laikas),nbf
(galioja ne anksčiau nei),iss
(leidėjas) iraud
(auditorija). - Patikrinkite
exp
pareiškimą: Įsitikinkite, kad JWT galiojimas nepasibaigęs. Nustatykite protingą prieigos rakto galiojimo laiką, kad sumažintumėte galimybių langą užpuolikams. - Patikrinkite
nbf
pareiškimą: Įsitikinkite, kad JWT nenaudojamas anksčiau nei jo galiojimo pradžios laikas. Tai apsaugo nuo pakartojimo atakų, kol prieigos raktas dar neturėtų būti naudojamas. - Patikrinkite
iss
pareiškimą: Patikrinkite, ar JWT išdavė patikimas leidėjas. Tai neleidžia užpuolikams naudoti JWT, kuriuos išdavė neautorizuotos šalys. - Patikrinkite
aud
pareiškimą: Patikrinkite, ar JWT skirtas jūsų programai. Tai neleidžia naudoti JWT, išduotų kitoms programoms, prieš jūsų programą. - Įdiekite neleistinų sąrašą (nebūtina): Kritinėms programoms apsvarstykite galimybę įdiegti neleistinų (arba atšaukimo) sąrašą, kad anuliuotumėte kompromituotus JWT prieš jų galiojimo pabaigą. Tai prideda sudėtingumo, bet gali žymiai pagerinti saugumą.
Pavyzdys: Pareiškimų patvirtinimas kode (Node.js su 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. Saugus JWT saugojimas kliento pusėje
Tai, kaip JWT saugomi kliento pusėje, daro didelę įtaką saugumui:
- Venkite vietinės saugyklos (Local Storage): JWT saugojimas vietinėje saugykloje daro juos pažeidžiamus XSS atakoms. Jei užpuolikas gali įterpti JavaScript kodą į jūsų programą, jis gali lengvai pavogti JWT iš vietinės saugyklos.
- Naudokite tik HTTP slapukus (HTTP-Only Cookies): Saugokite JWT tik HTTP slapukuose su
Secure
irSameSite
atributais. Tik HTTP slapukų negali pasiekti JavaScript, kas sumažina XSS riziką.Secure
atributas užtikrina, kad slapukas būtų perduodamas tik per HTTPS.SameSite
atributas padeda išvengti CSRF atakų. - Apsvarstykite atnaujinimo raktus (Refresh Tokens): Įdiekite atnaujinimo rakto mechanizmą. Trumpalaikiai prieigos raktai naudojami tiesioginei autorizacijai, o ilgesnio galiojimo atnaujinimo raktai naudojami naujiems prieigos raktams gauti. Saugokite atnaujinimo raktus saugiai (pvz., duomenų bazėje su šifravimu).
- Įdiekite CSRF apsaugą: Naudodami slapukus, įdiekite CSRF apsaugos mechanizmus, tokius kaip sinchronizatoriaus raktai arba „Double Submit Cookie“ modelis.
Pavyzdys: Tik HTTP slapukų nustatymas (Node.js su Express)
app.get('/login', (req, res) => {
// ... autentifikavimo logika ...
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, // Gamybinėje aplinkoje nustatykite į 'true'
sameSite: 'strict', // arba 'lax', priklausomai nuo jūsų poreikių
maxAge: 15 * 60 * 1000 // 15 minučių
});
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true, // Gamybinėje aplinkoje nustatykite į 'true'
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 dienos
});
res.send({ message: 'Login successful' });
});
4. Apsauga nuo algoritmų painiavos atakų
Algoritmų painiava yra kritinis pažeidžiamumas. Štai kaip to išvengti:
- Aiškiai nurodykite leidžiamus algoritmus: Tikrindami JWT, aiškiai nurodykite leidžiamus pasirašymo algoritmus. Nesikliaukite JWT biblioteka, kad ji automatiškai nustatytų algoritmą.
- Nepasitikėkite
alg
antrašte: Niekada aklai nepasitikėkitealg
antrašte JWT. Visada patikrinkite ją pagal iš anksto nustatytą leidžiamų algoritmų sąrašą. - Naudokite stiprų statinį tipizavimą (jei įmanoma): Kalbose, kurios palaiko statinį tipizavimą, įgyvendinkite griežtą rakto ir algoritmo parametrų tipų tikrinimą.
Pavyzdys: Apsauga nuo algoritmų painiavos (Node.js su jsonwebtoken
)
const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'] // Aiškiai leisti tik RS256
});
console.log(decoded);
} catch (error) {
console.error('JWT validation failed:', error);
}
5. Tinkamų prieigos rakto galiojimo ir atnaujinimo mechanizmų diegimas
Prieigos rakto galiojimo laikas yra svarbus saugumo aspektas:
- Naudokite trumpalaikius prieigos raktus: Laikykite prieigos raktus trumpalaikius (pvz., 5–30 minučių). Tai apriboja poveikį, jei raktas yra kompromituotas.
- Įdiekite atnaujinimo raktus: Naudokite atnaujinimo raktus, kad gautumėte naujus prieigos raktus nereikalaudami vartotojo pakartotinės autentifikacijos. Atnaujinimo raktai gali turėti ilgesnį galiojimo laiką, tačiau turi būti saugomi saugiai.
- Įdiekite atnaujinimo raktų rotaciją: Keiskite atnaujinimo raktus kiekvieną kartą, kai išduodamas naujas prieigos raktas. Tai anuliuoja seną atnaujinimo raktą, apribojant potencialią žalą, jei atnaujinimo raktas būtų kompromituotas.
- Apsvarstykite seansų valdymą: Jautrioms programoms apsvarstykite galimybę įdiegti serverio pusės seansų valdymą kartu su JWT. Tai leidžia atšaukti prieigą detaliau.
6. Apsauga nuo prieigos rakto vagystės
Apsauga nuo prieigos rakto vagystės yra labai svarbi:
- Įdiekite griežtą turinio saugumo politiką (CSP): Naudokite CSP, kad išvengtumėte XSS atakų. CSP leidžia nurodyti, iš kurių šaltinių leidžiama įkelti išteklius (scenarijus, stilius, paveikslėlius ir kt.) jūsų svetainėje.
- Valykite vartotojo įvestį: Valykite visą vartotojo įvestį, kad išvengtumėte XSS atakų. Naudokite patikimą HTML valymo biblioteką, kad pašalintumėte potencialiai kenksmingus simbolius.
- Naudokite HTTPS: Visada naudokite HTTPS, kad šifruotumėte ryšį tarp kliento ir serverio. Tai neleidžia užpuolikams perimti tinklo srauto ir pavogti JWT.
- Įdiekite HSTS (HTTP Strict Transport Security): Naudokite HSTS, kad nurodytumėte naršyklėms visada naudoti HTTPS bendraujant su jūsų svetaine.
7. Stebėjimas ir registravimas
Efektyvus stebėjimas ir registravimas yra būtini norint aptikti ir reaguoti į saugumo incidentus:
- Registruokite JWT išdavimą ir patvirtinimą: Registruokite visus JWT išdavimo ir patvirtinimo įvykius, įskaitant vartotojo ID, IP adresą ir laiko žymą.
- Stebėkite įtartiną veiklą: Stebėkite neįprastus modelius, tokius kaip keli nesėkmingi prisijungimo bandymai, JWT naudojimas iš skirtingų vietų vienu metu arba greiti prieigos rakto atnaujinimo prašymai.
- Nustatykite įspėjimus: Nustatykite įspėjimus, kad praneštumėte apie galimus saugumo incidentus.
- Reguliariai peržiūrėkite žurnalus: Reguliariai peržiūrėkite žurnalus, kad nustatytumėte ir ištirtumėte įtartiną veiklą.
8. Užklausų ribojimas
Įdiekite užklausų ribojimą, kad išvengtumėte „brute-force“ atakų ir paslaugos trikdymo (DoS) atakų:
- Ribokite prisijungimo bandymus: Ribokite nesėkmingų prisijungimo bandymų skaičių iš vieno IP adreso ar vartotojo paskyros.
- Ribokite prieigos rakto atnaujinimo užklausas: Ribokite prieigos rakto atnaujinimo užklausų skaičių iš vieno IP adreso ar vartotojo paskyros.
- Ribokite API užklausas: Ribokite API užklausų skaičių iš vieno IP adreso ar vartotojo paskyros.
9. Nuolatinis atsinaujinimas
- Atnaujinkite bibliotekas: Reguliariai atnaujinkite savo JWT bibliotekas ir priklausomybes, kad pataisytumėte saugumo pažeidžiamumus.
- Laikykitės saugumo geriausių praktikų: Būkite informuoti apie naujausias saugumo geriausias praktikas ir pažeidžiamumus, susijusius su JWT.
- Atlikite saugumo auditus: Reguliariai atlikite savo programos saugumo auditus, kad nustatytumėte ir pašalintumėte galimus pažeidžiamumus.
Globalūs aspektai JWT saugumui
Diegiant JWT globalioms programoms, atsižvelkite į šiuos dalykus:
- Laiko juostos: Užtikrinkite, kad jūsų serveriai būtų sinchronizuoti su patikimu laiko šaltiniu (pvz., NTP), kad išvengtumėte laikrodžio sinchronizavimo problemų, kurios gali paveikti JWT patvirtinimą, ypač
exp
irnbf
pareiškimus. Apsvarstykite galimybę nuosekliai naudoti UTC laiko žymas. - Duomenų privatumo reglamentai: Atsižvelkite į duomenų privatumo reglamentus, tokius kaip GDPR, CCPA ir kitus. Sumažinkite asmeninių duomenų kiekį, saugomą JWT, ir užtikrinkite atitiktį atitinkamiems reglamentams. Jei reikia, šifruokite jautrius pareiškimus.
- Internacionalizacija (i18n): Rodydami informaciją iš JWT pareiškimų, užtikrinkite, kad duomenys būtų tinkamai lokalizuoti pagal vartotojo kalbą ir regioną. Tai apima tinkamą datų, skaičių ir valiutų formatavimą.
- Teisinis atitikimas: Būkite informuoti apie bet kokius teisinius reikalavimus, susijusius su duomenų saugojimu ir perdavimu skirtingose šalyse. Užtikrinkite, kad jūsų JWT diegimas atitiktų visus taikomus įstatymus ir reglamentus.
- Kryžminės kilmės išteklių dalijimasis (CORS): Tinkamai sukonfigūruokite CORS, kad jūsų programa galėtų pasiekti išteklius iš skirtingų domenų. Tai ypač svarbu naudojant JWT autentifikacijai tarp skirtingų paslaugų ar programų.
Išvada
JWT siūlo patogų ir efektyvų būdą tvarkyti autentifikaciją ir autorizaciją, tačiau jie taip pat kelia potencialių saugumo rizikų. Laikydamiesi šių geriausių praktikų, galite žymiai sumažinti pažeidžiamumų riziką ir užtikrinti savo globalių programų saugumą. Nepamirškite būti informuoti apie naujausias saugumo grėsmes ir atitinkamai atnaujinti savo diegimą. Saugumo prioritetų nustatymas visame JWT gyvavimo cikle padės apsaugoti jūsų vartotojus ir duomenis nuo neautorizuotos prieigos.