Stealing JWTs in localStorage via XSS
字数 1640 2025-08-26 22:11:51
JSON Web Token (JWT) 安全与XSS攻击防护指南
1. JWT基础概念
1.1 什么是JWT
JSON Web Token (JWT) 是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。JWT通常用于身份验证和信息交换,由三部分组成,用点(.)分隔:
- Header(头部)
- Payload(有效载荷)
- Signature(签名)
1.2 JWT的组成部分
-
Header:
- 通常包含两部分:token类型("JWT")和使用的签名算法(如HMAC SHA256或RSA)
- 示例:
{"alg": "HS256", "typ": "JWT"}
-
Payload:
- 包含声明(claims),即关于实体(通常是用户)和其他数据的声明
- 三种类型的声明:
- 注册声明(预定义):如iss(签发者)、exp(过期时间)、sub(主题)等
- 公开声明
- 私有声明(自定义)
-
Signature:
- 用于验证消息在传输过程中没有被篡改
- 创建方式:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
2. JWT与传统Cookie的比较
2.1 存储位置差异
| 特性 | JWT | 传统Cookie |
|---|---|---|
| 默认存储位置 | localStorage/sessionStorage | Cookie容器 |
| 持久性 | localStorage持久,sessionStorage临时 | 可配置 |
| 可访问性 | 可通过JavaScript访问 | 可配置为HttpOnly |
| 自动发送 | 需手动设置Authorization头 | 自动随请求发送 |
2.2 安全特性对比
-
传统Cookie保护机制:
- HttpOnly:防止JavaScript访问
- Secure:仅通过HTTPS传输
- SameSite:限制跨站发送
- Domain/Path:限制作用域
-
JWT存储风险:
- 默认存储在localStorage中,完全暴露给JavaScript
- 无内置保护机制
- 易受XSS攻击窃取
3. JWT安全风险:XSS攻击案例
3.1 攻击场景
当JWT存储在localStorage中时,攻击者可通过XSS漏洞:
- 注入恶意脚本
- 读取localStorage中的JWT
- 将窃取的token发送到攻击者控制的服务器
3.2 攻击方法详解
-
简单读取方法:
alert(localStorage.getItem('key'));需要知道具体的key名称
-
完整转储方法:
JSON.stringify(localStorage)可获取localStorage中所有内容
-
实际攻击Payload示例:
4. 防御措施
4.1 存储方案优化
-
避免在localStorage存储敏感信息:
- 优先考虑使用HttpOnly Cookie存储JWT
- 如必须使用localStorage,确保有额外保护层
-
实施严格的CSP策略:
Content-Security-Policy: script-src 'self'
4.2 JWT传输安全
-
使用Authorization头而非URL:
- 防止token出现在浏览器历史、日志等
-
设置短期有效期:
- 使用较短的exp声明
- 实现token刷新机制
4.3 其他防护措施
-
输入验证与输出编码:
- 防止XSS注入
-
定期安全审计:
- 检查JWT实现是否存在已知漏洞
-
使用最新库:
- 确保使用的JWT库没有已知漏洞
5. 最佳实践总结
-
存储选择:
- 优先使用HttpOnly Cookie而非localStorage
- 如必须使用localStorage,确保有XSS防护
-
传输安全:
- 始终使用HTTPS
- 避免URL传输token
-
token设计:
- 设置合理有效期
- 避免在token中存储敏感信息
-
应用安全:
- 实施严格的CSP
- 定期安全测试
通过理解JWT的工作原理和安全风险,并实施适当的防护措施,可以显著提高Web应用的安全性,防止令牌窃取和会话劫持攻击。