2011-06-06 85 views
2

我們正在爲客戶構建一個ASP.NET MVC3 Web應用程序。將用戶名/密碼存儲在會話狀態以便進行一次性密碼登錄是否安全?

在此應用程序中,客戶端希望用戶使用他的用戶名/密碼組合登錄。但是,如果用戶名密碼正確,則應將一次性引腳發送給用戶的手機。用戶只有進入正確的一次性引腳(OTP)後才能進行認證。

所以我想知道如果下面的解決方案是安全的:

  1. 用戶用自己的用戶名和密碼登錄。我們使用Membership.ValidateUser來驗證用戶名/密碼,但我們尚未設置Auth Cookie。
  2. 我們在會話中存儲用戶的用戶名和密碼。
  3. 我們存儲的事實是用戶在會話中是「一半」登錄的。
  4. 我們重定向回登錄頁面。
  5. 用戶現在有機會進入OTP並再次提交給服務器。
  6. 我們驗證用戶名/密碼/ OTP組合。
  7. 如果有效,我們設置表單身份驗證Cookie。

PS:這一切都將發生在SSL上。

假設的登錄頁面可能看起來如下(注意三種狀態):

<h2>Log On</h2> 
<div> 
    @if (User.Identity.IsAuthenticated) 
    { 
     <p class="green bold"> 
      You are logged-on fully. Your UserName and Password match, and the OTP you have entered was correct. 
     </p> 
     <form action="/Account/LogOff"> 
      <input type="submit" value="Log Off" /> 
     </form> 
    } 
    else if (ViewBag.AwaitingOTP) 
    { 
     <p> 
      Hi @ViewBag.UserName 
     </p> 
     <p class="orange"> 
      Step 2/2: Please enter the OTP sent to your cell phone. 
     </p> 
     <form method="post" action="/Account/VerifyOTPAndLogOn"> 
      <input name="otp" type="text" placeholder="One-Time Pin" /> 
      <input type="submit" /> 
     </form> 
    } 
    else 
    { 
     <p> 
      Hi stranger! 
     </p> 
     <p class="orange"> 
      Step 1/2: Please enter your username and password. 
     </p> 
     <form method="post" action="/Account/LogOnHalfwayAndRequestOTP"> 
      <input name="userName" type="text" placeholder="userName" /> 
      <input name="password" type="password" placeholder="password" /> 
      <input type="submit" value="Log On" /> 
     </form> 
    } 

</div> 

控制器代碼如下:

public class AccountController : ControllerBase 
{ 

    public bool HalfwayLoggedOnStillAwaitingOTP 
    { 
     get 
     { 
      if (Session["AwaitingOTP"] != null) 
       return (bool)Session["AwaitingOTP"]; 

      return false; 
     } 
     set 
     { 
      Session["AwaitingOTP"] = value; 
     } 
    } 


    public ActionResult LogOn() 
    { 
     ViewBag.AwaitingOTP = HalfwayLoggedOnStillAwaitingOTP; 
     ViewBag.UserName = Session["UserName"] ?? null; 

     return View(); 
    } 


    public ActionResult LogOnHalfwayAndRequestOTP(string userName, string password) 
    { 
     //Authenticate user, but not fully... (i.e. we're not setting FormsAuthentication.SetAuthCookie yet) 
     if (Membership.ValidateUser(userName, password)) 
      HalfwayLoggedOnStillAwaitingOTP = true; 
     else 
      HalfwayLoggedOnStillAwaitingOTP = false; 

     ViewBag.AwaitingOTP = HalfwayLoggedOnStillAwaitingOTP; 
     ViewBag.UserName = Session["UserName"] ?? null; 

     //... 
     //...Call service that sends OTP to the user's cellPhone. 
     //... 

     return View("LogOn"); 
    } 


    public ActionResult VerifyOTPAndLogOn(string otp) 
    { 
     string userName = (string) Session["UserName"]; 
     string password = (string) Session["Password"]; 
     if (OTPIsValid(otp, userName, password)) 
     { 
      //Set the Forms Auth cookie... 
      FormsAuthentication.SetAuthCookie(userName, false); 

      return RedirectToAction("Index", "Home"); 
     } 
     else 
     { 
      //Display a nice error message here. 
      return View(); 
     } 


    } 

    private bool OTPIsValid(string otp, string userName, string password) 
    { 
     //... 
     //...Validate OTP here. For now we assume the user entered the correct OTP. 
     //... 
     return true; 
    } 
} 

是否有在此實現的任何安全漏洞?我不確定在會話中存儲用戶名/密碼有多安全,或者如果在設置Session [「AwaitingOTP」]值時相信用戶真的得到認證是安全的。

回答

1

我會用我過去24小時收集的信息回答我自己的問題。希望這是正確的。

讓我擔心的是我們提出的解決方案是我們僅僅依靠會話狀態存儲用戶身份驗證的短時間。 (因爲只有在輸入了OTP後,我們纔會使用適當的表單身份驗證)。

ASP.NET會話密鑰存儲在cookie中。它是加密的,所以相對安全。但它仍然是脆弱的標準窗體身份驗證同樣的威脅:

  • XSS
  • 人在這方面的中間人攻擊(SSL將防止這一點)
  • 曲奇盜竊

我會改變建議的解決方案,不要在會話中存儲用戶的密碼(並且只存儲他的用戶名)。我會確保使用SSL。