6 分鐘閱讀

近期系統碰到一個漏洞,攻擊者可以透過攻擊者冒充其他登入的使用者

在使用 Cookie 紀錄登入狀態的 ASP.NET MVC 系統中,
若攻擊者能成功竊取使用者的認證 Cookie(例如 Session ID 或身份憑證),
只要將該 Cookie 複製到自己的瀏覽器中,即可冒用該用戶,繞過伺服器的身份驗證。

透過以下兩個方法做防禦

1. DB 綁定來源資訊(IP、User-Agent等)

// 在登入成功後
 user.LoginIP = Request.UserHostAddress;
 db.SaveChanges();

在用戶登入後,記錄來源 IP 或 User-Agent,之後每次請求都驗證

2. 請求時的監控

此步驟為關鍵安全機制之一:

  1. 驗證使用者登入狀態
    每當有請求進入時,系統會在 Application_AcquireRequestState 事件中檢查使用者是否已登入(IsAuthenticated == true)。

  2. IP 驗證邏輯
    若使用者已登入,系統會比對:

    • 當前請求的 IP(Request.UserHostAddress

    • 使用者登入時儲存的原始 IP(由資料庫取得)

    若兩者不一致,視為潛在異常行為,系統會強制導向登出(/Account/Logout)。

  3. 避免登出遞迴陷阱
    由於 Application_AcquireRequestState 會在每次請求前執行,若沒有排除登入、登出、驗證等網址,將導致如下無限循環:

    • 使用者發送請求 → 偵測到 IP 不一致 → 導向 /Account/Logout

    • /Account/Logout 也觸發 AcquireRequestState → 再次驗證失敗 → 再次導向 /Account/Logout

    • 造成實際登出流程永遠無法執行

    為避免此情況,需排除以下路徑的檢查:

    • /account/login

    • /account/logout

    • /account/verify

  protected void Application_AcquireRequestState(object sender, EventArgs e)
  {
      var ctx = HttpContext.Current;
      var path = ctx.Request.Path.ToLower();
      if (ctx.User.Identity.IsAuthenticated && 
          !path.Contains("account/logout") && 
          !path.Contains("account/login") &&  
          !path.Contains("account/verify"))
      {
          // 取得當前 IP

          var currentIP = ctx.Request.UserHostAddress;

          var originalIP = UserRepository.GetUserById(ctx.User.Identity.Name);

          // 驗證 IP
          if (originalIP != null && originalIP != currentIP)
          {
              // IP 不一致,強制登出
              ctx.Response.Redirect("/Account/Logout");
          }
      }
  }

標籤:

更新時間: