本文目录导读:

防止会话固定攻击的核心方法是拒绝接受客户端提供的会话标识符(Session ID),并确保用户登录后生成新的会话,以下是具体的安全措施:
登录后重新生成会话ID(最关键的防御)
- 原理:攻击者通过URL、表单或Cookie给用户设置一个已知的会话ID(
SID=abc123),用户登录后,服务端仍使用该ID,攻击者即可冒充用户。 - 操作:在用户成功登录(或权限升级)时,立即销毁旧会话,并生成一个新的、随机的会话ID。
- Java (Servlet):
request.changeSessionId();或session.invalidate();后创建新session。 - PHP:
session_regenerate_id(true); - ASP.NET:
Session.Abandon();后重新创建。
- Java (Servlet):
- 注意:不仅登录时要更换,在用户执行关键操作(如修改密码、支付)前也应考虑更换。
不通过URL传递会话ID(避免泄露)
- 风险:URL中的会话ID容易被浏览器历史、Referer头、代理日志截获,也容易被攻击者通过链接直接固定。
- 操作:
- 强制使用Cookie传递会话ID,并禁止URL重写。
- 在Web服务器(如Apache Nginx)或应用框架中关闭基于URL的会话传输。
- PHP设置:
ini_set('session.use_only_cookies', 1);并设置session.use_trans_sid = 0。
设置安全的Cookie属性
- HttpOnly:防止JavaScript读取Cookie(抵御XSS攻击窃取会话ID)。
Set-Cookie: SID=xxx; HttpOnly
- Secure:仅允许HTTPS传输,防止中间人截获。
Set-Cookie: SID=xxx; Secure
- SameSite:限制跨站请求携带Cookie(抵御CSRF和部分会话固定攻击)。
Set-Cookie: SID=xxx; SameSite=Strict或Lax
- Domain & Path:尽量严格限定,不设置宽泛的域(如
domain=.example.com)和路径。
绑定会话与用户属性(额外加固)
- 方法:在服务器端会话中存储用户的登录IP地址、User-Agent或加密的客户端指纹。
- 校验:每次请求时比对当前请求的IP/User-Agent与会话中存储的是否一致,如果变化,可强制要求重新登录或销毁会话。
- 注意:IP校验在移动网络或代理环境下可能会误伤,需平衡安全与用户体验(如仅在校验敏感操作时使用)。
设置合理的会话过期策略
- 空闲超时:用户无操作15~30分钟后自动失效。
- 绝对超时:无论是否活跃,登录一段时间(如24小时)后强制失效。
- 退出登录:用户主动注销时,彻底销毁服务端和客户端的会话数据(清除Cookie和服务器Session)。
其他防御措施
- 验证Referer/Origin:对关键操作(如修改密码)校验请求来源是否可信。
- 使用CSRF Token:虽非直接防御会话固定,但能防止攻击者利用用户的会话发起跨站请求。
- 定期轮换会话ID:即使在非登录状态下,也可每隔一段时间(如30分钟)自动更换会话ID(
session_regenerate_id())。
最重要的几件事
- 登录后必须更换会话ID(禁止接受用户传入的旧ID)。
- 只用Cookie传递ID,并设置
HttpOnly、Secure、SameSite。 - 附加验证:绑定IP/User-Agent,防止被盗取的会话被异地使用。
通过以上措施,即使攻击者成功将某会话ID固定到用户浏览器,用户登录后该ID也会作废,攻击无法得逞。