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" />

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM