本文目录导读:

会话固定攻击(Session Fixation)是一种利用Web应用程序在用户登录前后使用相同Session ID的漏洞,诱使受害者使用攻击者设定的Session ID进行登录,从而窃取会话权限的攻击方式。
要防御和规避会话固定攻击,需要从开发架构和运维配置两个层面入手,以下是具体且可落地的防御方法:
核心防御:登录成功后销毁旧会话,生成新会话
这是最根本、最有效的防御措施,在用户完成身份验证(登录)之后,程序必须主动销毁当前的Session,并立即创建一个全新的Session(包含新的Session ID)。
- 具体做法:在登录验证通过后调用
session_regenerate_id()或类似的函数。 - 原因:即使攻击者诱导用户使用了特定的Session ID,一旦用户登录,服务器会把旧的Session数据清除并分配给用户一个全新的、由服务器生成的随机ID,攻击者持有的旧ID将变得无效。
- 示例代码(PHP):
session_start(); // 假设用户验证通过 if (用户验证成功) { // 清除旧Session数据 $_SESSION = array(); // 销毁旧Session session_destroy(); // 开始新Session(服务器自动分配新ID) session_start(); // 设置用户登录后的会话变量 $_SESSION['user_id'] = $user_id; // 防止会话劫持的额外措施:绑定IP或User-Agent(谨慎使用) $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT']; }
增强防御措施(推荐结合使用)
A. 设置合理的会话过期机制
- 短生命周期:设置Session的过期时间,即使ID被固定,也会在短时间内失效。
- 闲置超时:如果用户一段时间不操作,自动销毁会话,Web应用如银行系统通常设置15分钟无操作自动退出。
- 绝对超时:无论是否活跃,登录后24小时或更短时间强制重新认证。
B. 绑定会话与用户环境(谨慎使用)
浏览器会向服务器发送多种标识,可以将这些标识与Session绑定,用于校验请求的合法性。
- IP地址绑定:将Session绑定到登录时的IP地址,缺点是用户使用手机网络或移动办公时IP变化会导致频繁掉线。
- User-Agent绑定:将Session绑定到浏览器类型/版本,User-Agent通常不会在正常使用中变化,是较稳定的校验项。
C. 使用HTTPS并设置Secure & HttpOnly Cookie
- Secure标志:确保Session Cookie只通过HTTPS发送,防止中间人攻击窃取Cookie。
- HttpOnly标志:禁止客户端JavaScript访问Cookie(
document.cookie可以读取没有HttpOnly标志的Cookie,但无法读取HttpOnly的Cookie),这能防御XSS(跨站脚本攻击)窃取会话。 - SameSite属性:设置
SameSite=Lax或Strict,防止CSRF(跨站请求伪造)攻击通过第三方网站发起请求携带Cookie。
主动检测与规避策略
A. 在登录页面植入隐藏Token
- 在用户访问登录页面时,为一个特定表单字段生成一个隐藏的随机Token,并将其存储在服务器的Session中。
- 用户提交登录表单时,服务器校验该Token是否匹配。
- 原理:攻击者很难同时固定Session ID和窃取到页面上的动态Token。
B. 监控会话ID的异常变化
- 记录用户的Session创建时间、上次活动时间,如果发现同一个Session ID在不同浏览器、不同User-Agent或短时间内出现多次可疑操作,可以主动销毁该会话并强制用户重新登录。
开发者检查清单
如果你正在开发Web应用,请确保代码流程符合以下步骤:
- 用户请求登录页面:服务器分配一个新Session ID(
session_start())。 - 用户提交用户名/密码:服务器验证凭据。
- 验证成功:立即执行:
- 销毁旧Session数据(
session_destroy())。 - 分配新Session ID(
session_regenerate_id(true))。 - 将用户信息写入新Session。
- 销毁旧Session数据(
- 后续请求:使用新ID进行通信。
特殊场景注意
- API/无状态JWT:如果你使用的是JWT(JSON Web Token)令牌,则不存在会话固定问题,但需要注意:登录成功后,必须生成一个全新的JWT令牌,并废弃之前可能持有的任何令牌(设置较短的过期时间)。
- 第三方登录(OAuth):在使用OAuth登录后,同样要销毁旧会话,生成新会话。