JWT漏洞如何防护修复

wen 网络安全 29

本文目录导读:

JWT漏洞如何防护修复

  1. 修复算法混淆攻击(最核心的漏洞)
  2. 别把敏感信息放在Payload里(且未加密)
  3. 修复密钥泄露或弱密钥
  4. 加强Token存储安全(防止XSS/CSRF导致泄露)
  5. 完善Token生命周期管理(防重放与劫持)
  6. 验证关键声明(防止未授权访问)
  7. 防止JWT被篡改后依然有效
  8. 防护清单

JWT(JSON Web Token)本身是一种规范,其安全性取决于实现方式使用场景,要防护和修复JWT相关的漏洞,需要从算法、密钥管理、存储、验证流程等多个维度入手。

以下是针对常见JWT漏洞的防护修复指南:

修复算法混淆攻击(最核心的漏洞)

漏洞原理: 攻击者将JWT头部的algRS256(非对称加密)篡改为HS256(对称加密),并使用公钥(通常是公开的)作为密钥进行签名,服务器如果未严格校验算法类型,会使用公钥作为HS256的密钥进行验证,导致攻击成功。

  • 修复方案:

    • 严格校验算法白名单: 在服务端验证JWT时,必须明确指定允许的算法列表。不要从JWT的Header中动态获取算法。

    • 代码示例(Node.js jsonwebtoken库):

      // 错误做法:从Header动态获取算法
      jwt.verify(token, secretOrPublicKey); 
      // 正确做法:强制指定算法,拒绝非预期算法
      jwt.verify(token, publicKey, { algorithms: ['RS256'] }); // 只允许RS256
    • 拒绝none算法: 确保服务器拒绝算法为none的JWT令牌,或明确禁用none算法。

别把敏感信息放在Payload里(且未加密)

漏洞原理: JWT的Payload只是Base64编码,不是加密,任何人只要拿到Token,就能解码看到Payload内容(如密码、身份证号)。

  • 修复方案:
    • 清除敏感数据: JWT中只存放必要且不敏感的信息,例如用户ID(User ID)、角色(Role)、过期时间(exp),敏感数据(密码、信用卡号、手机号)要放在服务端的Session或数据库中。
    • 使用JWE(加密): 如果必须传递敏感信息,使用JWE(JSON Web Encryption)对Payload进行加密,而不是仅使用JWS(签名)。

修复密钥泄露或弱密钥

漏洞原理: 使用简单的字符串(如"secret")作为HMAC密钥,或RSA私钥被泄露。

  • 修复方案:
    • 使用强随机密钥: HMAC密钥长度至少256位(32字节),使用密码学安全的随机生成器生成。
    • 定期轮换密钥: 定期更换签名密钥(Key Rotation),旧令牌在到期前仍然有效,但新令牌使用新密钥签发。
    • 优先使用非对称算法: 服务端负责签名的私钥要严格保管(可放在环境变量、密钥管理服务KMS或硬件安全模块HSM中),公钥可以安全分发给其他服务。

加强Token存储安全(防止XSS/CSRF导致泄露)

漏洞原理: 开发者将JWT存储在localStoragesessionStorage中,一旦网站存在XSS漏洞,攻击者可以轻松窃取Token。

  • 修复方案:
    • 首选方案(加HttpOnly Cookie): 将JWT放在HttpOnlySecureSameSite=Strict的Cookie中,这样可以防止XSS读取Token,并利用SameSite属性防御CSRF。
    • 备选方案(Memory/Web Worker): 如果无法使用Cookie(如移动端或纯前端),将Token存储在JavaScript内存变量中(页面刷新会丢失,需要配合刷新令牌机制),或放在Web Worker中。
    • 避免方案: 不要将Token直接存在localStoragesessionStorage中。

完善Token生命周期管理(防重放与劫持)

漏洞原理: JWT一旦签发,在过期前永久有效(除非服务端有黑名单机制),如果Token被窃取,攻击者可以长期使用。

  • 修复方案:
    • 设置短时效的Access Token: Access Token过期时间应很短(如15-30分钟)。
    • 引入Refresh Token机制: 使用一个长期有效的(如7天)、存储在数据库或白名单中的Refresh Token来换取新的Access Token,Refresh Token被使用一次后应立即作废。
    • 服务端黑名单/吊销机制: 如果用户登出或修改密码,将旧的Access Token加入服务端的黑名单(牺牲无状态性换取安全性),或直接修改用户密码哈希值(使旧Token失效)。

验证关键声明(防止未授权访问)

漏洞原理: 服务端只验证签名,不验证aud(受众)、iss(签发者)等声明。

  • 修复方案:
    • 验证受众(aud): 确保Token是发给当前服务使用的。
    • 验证签发者(iss): 确保Token来自受信任的授权服务器。
    • 验证过期时间(exp): 默认必须检查,如果Token已过期,拒绝任何操作。

防止JWT被篡改后依然有效

漏洞原理: 极少数库有解析漏洞(如某些库会忽略签名验证)。

  • 修复方案:
    • 正确使用API: 务必使用.verify()方法验证签名,而不是.decode()直接解码。.decode()仅解码,不验证签名。

防护清单

漏洞类型 修复动作 优先级
算法混淆 服务端硬编码算法白名单,禁用none算法 最高
数据泄露 清除Payload中的敏感信息,或使用JWE加密
密钥泄露 使用强随机密钥,启用密钥轮换
存储不安全 使用HttpOnly Cookie存储Token
重放攻击 设置短Access Token + Refresh Token机制
未校验Claims 验证audissexp等标准声明
不当使用API 总是使用.verify(),不用.decode()

如果你使用的是成熟的框架(如Spring Security、Django REST Framework、ASP.NET Core Identity),建议启用其内置的JWT安全配置,少走弯路。

抱歉,评论功能暂时关闭!