JWT:結構和漏洞
1)什麼是JWT,在哪裏使用
JWT是以「Base 64Url」格式提供的緊湊型自給自足的聲明容器(claims)。Base64Url(payload).Base64Url(signature)`.
用於:- JWS(簽名令牌-真實/完整性),
- JWE(加密令牌-隱私),
- OIDC/OAuth2 作為訪問/ID令牌以及服務到服務的身份驗證。
優點:自主性、可緩存性、低開銷。缺點:錯誤驗證的風險,復雜的召回案例。
2) JWT結構
2.1標題(header, JSON)
最小值:算法和密鑰ID。
json
{ "alg": "ES256", "kid": "jwt-2025-10", "typ": "JWT" }
「alg」:簽名/加密算法(RS256/ES256/PS256/HS256等)。
「kid」:指向密鑰的指針(用於JWKS輪換)。
可選的密鑰來源是「jku」,「x5u」(請參閱漏洞§6。3).
2.2有效載荷(payload, JSON)
標準化汙名:- `iss` (issuer), `aud` (audience), `sub` (subject)
- 「exp」(到期時間),「nbf」(不早於),「iat」(發出)
- 「jti」(令牌ID,適合評論)
- 領域汙名:「scope/roles」,「tenant」,「kyc_level」等。
2.3簽名(簽名)
JWS = `sign(base64url(header) + "." + base64url(payload), private_key)`
驗證:嚴格符合公共密鑰,完全符合服務器期望的算法。
3)基本驗證不變量
1.該算法由資源-服務器配置(allow-list)固定,而不信任內容的「頭端」。alg`.
2.檢查「iss」和「aud」的精確匹配,「exp/nbf」-考慮一小部分「clock_skew」(± 30-60 s)。
3.僅在單個密鑰且沒有旋轉的情況下拒絕沒有「kid」的令牌;否則-要求「孩子」。
4.不信任任何未經對象級別授權的汙名(BOLA-first)。
5.Parsing-密碼反駁後;解碼前的基本尺寸檢查。
4) JWS vs JWE
JWS:已簽名,但我們正在閱讀。不要放在付費的PII/秘密中。
JWE:加密payload;更難整合,關鍵模型至關重要。
在大多數API中,對付費中的敏感數據的JWS+禁令就足夠了。
5)令牌生命周期
訪問:短時間(5-30分鐘)。
Refresh:更長(7-30天),rotate-on-use(一次性),保留「黑名單」'jti/sid'。
Revocation: TTL的「jti」列表,opaque令牌的內窺鏡,事件中「exp」的縮寫。
鍵輪換:重疊的JWKS(舊+新),請參閱「鍵輪換」文章。
6)頻繁的漏洞以及如何關閉它們
6.1 'alg=none'/變換算法
底線:服務器信任「alg」字段並接受未簽名的令牌。
保護:服務器上的硬allow-list算法;拒絕「無」和意想不到的含義。
6.2 RS256→HS256交換(對稱化)
底線:攻擊者將「alg」替換為HS256,並使用公共密鑰作為HMAC秘密。
保護:通過配置綁定算法的關鍵;不要將對稱/非對稱提供者混為一體「kid」。
6.3鍵註射(「kid/jku/x5u」)
腳本:- 「jku」表示攻擊者控制的JWKS(將滑動其密鑰)。
- 「x5u」/「x5c」濫用外部證書。
- 帶有路徑/SQL註入的"kid"("……/……/privkey。pem「」或「」OR 1=1-「」)。
- 忽略已刪除的「jku/x5u」或通過嚴格的allow-list域進行過濾。
- 「kid」僅用作本地目錄(表/kesh)中的密鑰,沒有文件路徑/SQL串聯。
- JWKS從受信任的URL,短的TTL,信道簽名/插入裝載。
6.4微弱的HS256秘密(野蠻人)
底線:HMAC秘密短/鴨→替換簽名。
保護:僅在KMS中使用不對稱性(RS/ES/PS)或秘密長度≥ 256位,秘密。
6.5缺失/未驗證的汙名
不「aud」/「iss」/「exp」 →令牌交叉服務或無限。
太長的「exp」 →損害的風險。
防守:要求全套汙名,「exp」短,「nbf」/「iat」用「clock_skew」驗證。
6.6 Replay和令牌盜竊
底線:令牌攔截/重播(log泄漏,XSS,MitM沒有TLS)。
保護:- TLS везде, `Secure`+`HttpOnly` cookie, SameSite=Lax/Strict.
- 合作夥伴的DPoP/PoP(令牌綁定到客戶端密鑰)和/或mTLS。
- 短「exp」,refresh旋轉,設備綁定。
6.7通過XSS/存儲泄漏
底線:JS可以在「localStorage」/「sessionStorage」中存儲JWT →。
保護:將訪問令牌存儲在HttpOnly Cookie(如果可以使用Cookie)+嚴格的CSP/Trusted Types中。
對於沒有Cookie的SPA,可以隔離內存中的令牌,最小程度地生活,並保護XSS。
6.8 CSRF
底線:在Cookie會議中,請求來自第三方網站。
保護:SameSite、anti-CSRF令牌(雙submit)、「起源/參考」檢查、Fetch-Metadata過濾器。
6.9 Oversize/大小濫用
底線:巨大的薪水/頭條,DoS的解析。
保護:標題/主體尺寸限制,早期檢索431/413,假粘貼套件。
6.10替代「typ」/「cty」
底線:嵌套的JOSE對象的類型混淆('typ:'JWT')。
保護:為了安全而忽略「typ/cty」,依靠固定的算法和粘貼方案。
7)代幣的儲存和轉讓
7.1個服務器API(機器到機器)
mTLS/HMAC,最好是JWT的不對稱性,渠道是通過mesh。
密鑰庫是KMS/HSM,定時輪換,重疊的JWKS。
7.2瀏覽器客戶端
HttpOnly Secure Cookie для access/refresh;短的TTL;更新-僅通過HTTPS下的「SameSite=None」通過「silent refresh」。
嚴格CSP,Trusted Types,防止XSS;對於SPA-如果可能,不要將令牌存儲在磁盤上。
8) JWKS,輪換和召回
JWKS由授權者發布;消費者緩存5-15分鐘。
輪換計劃:添加新的「kid」 →開始簽名→在N日後從 JWKS → purge中刪除舊的。
評論:「jti/sid」 c TTL列表;在事件中,暫時縮短「exp」和fors-logout(致殘refresh)。
9) Multi-tenant和最小化數據
只有在架構上需要時,才在令牌中包含「tenant」/「org」;否則,通過「子」從PDP中拉動屬性。
沒有PII;最低限度的汙名→減少泄漏和汙染的風險。
10)實用驗證清單(資源服務器)
- Parsim僅在驗證簽名和基本尺寸限制之後。
- 「alg」來自配置;拒絕意想不到的。
- 檢查'iss' ∧ 'aud '∧ 'exp' ∧ 'nbf' ∧ 'iat'(帶有'clock_skew')。
- 通過本地目錄/JWKS(簡稱TTL)檢查「kid」。
- 篩選/歸一化外部指針("jku/x5u"-僅allow-list")。
- 限制粘合劑的長度/組成(圖)。
- 應用對象資源授權(BOLA-first)。
- 標記「kid」,「sub」,「aud」,「iss」,「jti」,「exp」,「tenant」,「trace_id」(沒有PII)。
- 簽名錯誤,逾期,輪換審核的度量。
11)安全策略示例(偽)
11.1算法期望配置
yaml jwt:
expected_issuer: "https://auth. example. com"
expected_audience: ["wallet-service"]
allowed_algs: ["ES256"] # fix the jwks_url: "https ://auth. example. com/.well-known/jwks. json"
jwks_cache_ttl: 600s clock_skew: 60s required_claims: ["iss","aud","sub","exp","iat"]
11.2遠程「jku/x5u」豁免'
yaml reject_untrusted_key_sources: true allowed_jku_hosts: ["auth. example. com"] # if absolutely necessary
11.3評論列表示例(Redis)
pseudo if redis. exists("revoke:jti:" + jti) then deny()
if now() > exp then deny()
12)可觀察性和力學
Метрики: `jwt_verify_fail_total{reason}`, `jwt_expired_total`, `jwks_refresh_total`, доля `kid`.
Logs(結構化):'iss/aud/sub/kid/jti/exp/tenant/trace_id'(故障原因)。
Dashbords:「即將到期」,驗證錯誤激增,按地區/客戶分配。
Alerts: 「verify_fail」(簽名/算法)、JWKS錯誤、過期令牌比例的增長。
13)反模式
信任令牌中的「alg」;支持「none」。
長壽命的訪問令牌和沒有refresh旋轉。
在沒有KMS的ENV中HS256簡短的秘密/秘密。
從任何域接受「jku/x5u」;動態地加載JWKS而不包含所有列表。
在JWS的付費下載中聚集PII/秘密。
如果存在XSS風險,則將令牌存儲在「本地存儲」中。
堵塞驗證錯誤(返回200「軟錯誤」)。
缺乏BOLA檢查,僅依賴「scope/role」。
14) iGaming/財務細節
克萊姆斯:「kyc_level」,「risk_tier」,「tenant」,嚴格的「aud」。
用於寫作操作(存款/收據),PoP/DPoP或mTLS的短TTL用於關鍵路由。
監管審核:不變的輸入/故障日誌,在區域範圍內存儲日誌。
合作夥伴/PSP 具有單獨的密鑰/「aud」,主鍵和單獨的JWKS。
15)準備就緒支票清單
- 硬allow-list算法;「none」被禁止。
[……]對iss/aud/exp/nbf/iat/jti"進行了檢查;短的「exp」。
- 重疊的JWKS,短緩存TTL;監視「kid」份額。
[] Refresh — rotate-on-use;TTL的「jti/sid」列表;評論的花花公子。
- 關鍵路線上的PoP/DPoP或mTLS。
- 瀏覽器的HttpOnly Cookie,CSP/Trusted Types訴XSS;CSRF保護。
- 沒有付費的PII;一組最小的粘合劑。
- 關於驗證和拒絕的度量/標誌;Alerta JWKS/verify_fail。
- 負面場景測試:RS→HS交換,'kid'註射,'jku' spoofing, oversize, clock-skew。
16) TL;DR
將算法和密鑰鎖定在服務器端,不要信任令牌中的「alg」,要求「iss/aud/exp/nbf/iat/jti」。通過重疊的JWKS輪換鑰匙,保持代幣短壽命,refresh一次性。安全地存儲令牌(Http-Only cookie for Web),盡量減少汙名,不要放下PII。關閉「jku/x5u/kid」-vectors,避免使用弱秘密HS256,在關鍵路徑上添加PoP/DPoP或mTLS,並始終對資源級別進行BOLA驗證。