Spring Security如何防止会话固定攻击(session fixation attack)

Session fixation attack(会话固定攻击)是利用服务器的session不变机制,借他人之手获得认证和授权,然后冒充他人。如果应用程序在用户首次访问它时为每一名用户建立一个匿名会话,这时往往就会出现会话固定漏洞。然后,一旦用户登录,该会话即升级为通过验证的会话。最初,会话令牌并未被赋予任何访问权限,但在用户通过验证后,这个令牌也具有了该用户的访问权限。

 

防止会话固定攻击,可以在用户登录成功后重新创建一个session id,并将登录前的匿名会话强制失效。Spring Security默认即可防止会话固定攻击。具体实现方式[3.1版本]如下:HttpConfigurationBuilder的createSessionManagementFilters方法用于配置文件中的session-management属性,并根据配置创建SessionManagementFilter。其首先读取session-fixation-protection并存入sessionFixationAttribute变量,随后,通过如下语句判断是否需要进行会话规定漏洞保护

boolean sessionFixationProtectionRequired = !sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION);

 需要说明的是在上述语句之前,如果发现sessionFixationAttribute变量没有赋值(例如,没有配置session-management属性),程序会采用如下语句确保缺省的session-fixation-protection=migrateSession

if (!StringUtils.hasText(sessionFixationAttribute)) {
            sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;

 

下面的判断,如果您配置了session-management并启用了concurrency-control,则向SessionManagementFilter注册ConcurrentSessionControlStrategy类;否则如果上面代码中的sessionFixationProtectionRequired = true或者配置了invalid-session-url,则向SessionManagementFilter注册SessionFixationProtectionStrategy类,由于ConcurrentSessionControlStrategy继承自SessionFixationProtectionStrategy,因此以上条件下,都会导致SessionFixationProtectionStrategy的策略被应用,而SessionFixationProtectionStrategy的策略,将在SessionManagementFilter中被执行,代码如下

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
  {
    HttpServletRequest request = (HttpServletRequest)req;
    HttpServletResponse response = (HttpServletResponse)res;

    if (request.getAttribute("__spring_security_session_mgmt_filter_applied") != null) {
      chain.doFilter(request, response);
      return;
    }

    request.setAttribute("__spring_security_session_mgmt_filter_applied", Boolean.TRUE);

    if (!this.securityContextRepository.containsContext(request)) {
      Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

      if ((authentication != null) && (!this.authenticationTrustResolver.isAnonymous(authentication)))
      {
        try {
          this.sessionAuthenticationStrategy.onAuthentication(authentication, request, response);
   
          ......

 

回头来看SessionFixationProtectionStrategy的onAuthentication方法,如下代码中,字体加粗部分,先设置当前的session失效,再创建一个新的session

public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response)
  {
    boolean hadSessionAlready = request.getSession(false) != null;

    if ((!hadSessionAlready) && (!this.alwaysCreateSession))
    {
      return;
    }

    HttpSession session = request.getSession();

    if ((hadSessionAlready) && (request.isRequestedSessionIdValid()))
    {
      String originalSessionId = session.getId();

      if (this.logger.isDebugEnabled()) {
        this.logger.debug("Invalidating session with Id '" + originalSessionId + "' " + (this.migrateSessionAttributes ? "and" : "without") + " migrating attributes.");
      }

      Map attributesToMigrate = extractAttributes(session);

      session.invalidate();
   
session = request.getSession(true); if (this.logger.isDebugEnabled()) { this.logger.debug("Started new session: " + session.getId()); } if (originalSessionId.equals(session.getId())) { this.logger.warn("Your servlet container did not change the session ID when a new session was created. You will not be adequately protected against session-fixation attacks"); } transferAttributes(attributesToMigrate, session); onSessionChange(originalSessionId, session, authentication); } }

 

最后,怎么关闭Spring Security的session-fixation-protection呢,由以上代码分析知,除了将session-fixation-protection设置为null以外,还不能设置诸如concurrency-control或invalid-session-url属性,举例如下

<session-management session-fixation-protection="none" />

 

 

posted @ 2013-05-12 20:16  Bryan Wong  阅读(9866)  评论(0编辑  收藏  举报