尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

JWT 安全漏洞与完整防护方案

JWT 安全漏洞与完整防护方案 一、JWT 基础与原理JWTJSON Web Token是目前最流行的跨域认证解决方案广泛应用于前后端分离项目、移动 APP、微服务架构等场景。JWT 是一个紧凑的、URL 安全的令牌由三部分组成Header头部声明类型和签名算法、Payload载荷存放用户信息和声明、Signature签名验证令牌完整性。三部分用点号连接格式为xxxxx.yyyyy.zzzzz。工作原理用户登录成功后服务器生成一个 JWT 令牌返回给客户端之后客户端每次请求都带上这个 JWT服务器收到请求后验证 JWT 的签名是否有效如果有效就信任令牌中的用户信息不需要再查数据库。JWT 的优点是无状态、易扩展、支持跨域非常适合分布式系统和微服务架构。但 JWT 的安全性非常依赖正确的实现和配置如果使用不当会存在很多安全漏洞攻击者可以伪造令牌、篡改信息、越权访问甚至直接登录任意用户账号。JWT 安全是 Web 安全和 API 安全中非常重要的一块也是渗透测试的重点项。二、JWT 常见安全漏洞1. 签名未校验最严重服务器收到 JWT 后根本不验证签名是否正确直接解析 Payload 中的用户信息。攻击者可以随意伪造任意用户的 JWT想登录谁就登录谁危害极大。这种漏洞虽然低级但在实际项目中并不少见尤其是一些赶工期的项目或者新手开发的系统。2. 算法混淆攻击Algo ConfusionJWT 的 Header 中声明了签名算法alg字段比如 HS256对称加密、RS256非对称加密。如果服务器端没有强制指定验证算法而是相信 JWT Header 中的 alg 字段攻击者就可以把算法改成 none无签名或者把非对称算法改成对称算法用公钥作为密钥来伪造签名从而绕过验证。特别是 none 算法攻击——把 alg 改成 none然后去掉签名部分有些 JWT库遇到 none 算法就会跳过签名验证直接认为令牌有效。这是非常经典的 JWT 漏洞。3. 弱密钥/密钥泄露对于 HS256 等对称加密算法签名和验证用的是同一个密钥。如果密钥太弱比如 123456、admin 等弱口令攻击者可以通过爆破的方式破解密钥如果密钥泄露了攻击者就可以用密钥伪造任意 JWT。很多开发者为了图方便用很简单的密钥或者把密钥硬编码在代码里很容易泄露。4. 敏感信息泄露JWT 的 Payload 部分只是 Base编码的不是加密的任何人拿到 JWT 都可以解码看到 Payload 里的所有内容。很多开发者误以为 JWT 是加密的把用户密码、身份证号、手机号、内部角色等敏感信息直接放在 Payload 里导致信息泄露。记住JWT 的内容是公开的只是通过签名保证了完整性和防篡改不保证保密性。5. 令牌无法吊销JWT 天生缺陷JWT 是无状态的一旦签发在过期之前一直有效服务器没有办法主动吊销某个 JWT。如果用户退出登录、修改密码、权限变更或者 JWT 被盗了原来的令牌仍然可以用直到过期。这是 JWT 的天生缺陷也是很多安全问题的根源。6. 过期时间设置过长有些系统为了用户体验把 JWT 的过期时间设得很长比如几天、几周甚至几个月。这样令牌被盗用后攻击者可以用很长时间危害很大。还有的系统干脆不设过期时间令牌永久有效这是非常危险的。7. 重放攻击攻击者截获了用户的 JWT就可以反复使用这个令牌来访问系统直到令牌过期。如果没有防重放机制被盗的令牌可以被一直滥用。8. Payload 可篡改签名失效的情况下如果签名验证有问题攻击者可以篡改Payload 中的内容比如把用户 ID 改成别人的、把角色改成管理员、提升权限等实现越权访问。三、JWT 完整防御方案1. 强制验证签名最基本最重要服务器端必须严格验证 JWT 的签名签名无效的令牌一律拒绝。不要自己实现 JWT 验证逻辑用成熟的、经过验证的 JWT 库并且正确配置。很多 JWT 漏洞都是因为自己写验证逻辑或者配置错误导致的。2. 强制指定算法禁止 none 算法服务端验证时必须强制指定使用的签名算法不能相信 JWT Header 中的 alg 字段。比如后端用的是 RS256验证时就明确指定用RS256 验证不管 Header 里写的是什么算法。同时明确禁止 none 算法防止算法混淆攻击。3. 使用强密钥妥善保管密钥对于对称加密算法HS256 等密钥要足够长、足够随机不要用弱密钥。密钥要妥善保管不要硬编码在代码里不要提交到代码仓库用配置中心、环境变量等安全方式管理。定期轮换密钥降低泄露后的影响。对于重要系统建议使用非对称加密算法RS256、ES256 等私钥只在签发端保存验证端只用公钥更安全。4. Payload 不放敏感信息永远记住 JWT 的 Payload 是公开的只是 Base编码谁都能解码。不要把密码、身份证、手机号、银行卡号等信息放在 Payload里。Payload 里只放必要的用户标识信息比如 user_id、username、role 等而且这些信息也尽量不要放太敏感的。5. 设置合理的过期时间JWT 的有效期要设置得短一些比如 15 分钟到 2 小时根据业务安全等级调整。令牌有效期越短被盗用后的危害时间越短。对于需要长时间登录的场景可以用 Refresh Token 机制来刷新 Access TokenAccess Token设短有效期Refresh Token 设长有效期并且 Refresh Token 可以被吊销。6. 实现令牌吊销机制解决无状态问题虽然 JWT 天生无状态但可以通过一些方案实现令牌吊销- 黑名单方案把需要吊销的令牌存入黑名单Redis 等验证时检查令牌是否在黑名单中。可以只存过期前的令牌过期后自动清理不会无限增长。- 版本号方案用户信息或权限变更时更新用户的 token 版本号JWT 里带上版本号验证时比对版本号不一致就拒绝。- 短有效期刷新令牌把 Access Token 有效期设得很短即使被盗用也很快失效配合 Refresh Token 来续期Refresh Token 可以被服务端吊销。7. 防重放攻击可以在 JWT 中加入 jtiJWT ID字段每个令牌有唯一 ID配合黑名单机制每个令牌只能用一次或者在一定时间内有效。或者结合请求时间戳、nonce 随机数等方式防止重放。8. 加强传输安全JWT 必须通过 HTTPS 传输防止在传输过程中被窃听。不要把JWT 放在 URL 参数中容易通过 Referer 泄露建议放在 Authorization 请求头中或者放在 HttpOnly 的 Cookie 中可以防 XSS 窃取。9. 权限二次校验不要完全信任 JWT 中的角色和权限信息关键操作还要从数据库或缓存中二次校验用户的权限状态。特别是高风险操作不能只靠 JWT 里的信息就放行。10. 安全审计与测试定期对 JWT 的实现进行安全测试检查是否存在签名未校验、算法混淆、弱密钥等常见漏洞。使用自动化安全扫描工具辅助检测但更重要的是人工渗透测试。四、常见误区JWT 是加密的里面的内容别人看不到大错特错JWT 只是 Base编码谁都能解码看内容签名只是防篡改不是加密用了 JWT 就绝对安全JWT 只是一种认证方案用不好漏洞百出JWT 无状态所以没法吊销可以通过黑名单、版本号等方案实现吊销只是需要额外设计令牌有效期设长一点用户体验好安全和体验要平衡重要系统必须设短有效期 用了 HTTPS 就不怕 JWT 泄露HTTPS 防传输窃听但防不了 XSS 窃取、防不了用户自己泄露对称加密和非对称加密随便用哪种都行重要系统、多服务场景建议用非对称加密更安全五、漏洞检测方法1. 签名测试把 JWT 的签名部分删掉或者改成错的看服务器是否还接受如果接受说明没有校验签名2. 算法混淆测试把 alg 改成 none去掉签名看服务器是否接受把 RS256改成 HS256用公钥当密钥签名看是否能绕过3. 密钥强度测试如果是对称算法尝试用常见弱密钥爆破看能否破解4. 敏感信息检测解码 JWT 的 Payload看是否包含信息5. 过期时间测试检查 JWT 的 exp 字段看过期时间是否合理6. 吊销测试用户退出登录或修改密码后原来的令牌是否还能使用7. 越权测试篡改 Payload 中的用户 ID、角色等信息看是否能越权访问前提是签名验证有问题或者服务端没二次校验。
返回列表