/// <summary> /// Detects the creation of a FormsAuthenticationCookie and FormsAuthenticationTicket /// during the processing of the current request (i.e., PostBack of Login page/action), /// records the state of both in a UserAuthenticationTicket, and adds it to the /// Provider. /// /// In the event that this request was already authenticated, it detects and handles /// sliding expiration on the Provider. /// </summary> /// <param name="sender">The HttpApplication that sent the request</param> /// <param name="e">Not used</param> private static void OnEndRequest(object sender, EventArgs e) { // EnhancedSecurity.InterceptFormsAuthenticationCookie(); FormsAuthenticationStatus status = EnhancedSecurity.GetFormsAuthStatus(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; HttpResponse response = context.Response; /* TODO: Remove this once working */ /* if (request.RawUrl.Contains("WebResource.axd")) { return; } */ if (status == FormsAuthenticationStatus.NotFound || status == FormsAuthenticationStatus.Invalid) { RequestAnalysis preAnalyzer = RequestAnalyzer.RetrieveAnalysis(RequestLifecyclePhase.BeginRequest); RequestAnalysis postAnalyzer = RequestAnalyzer.AnalyzeRequest(response.Cookies[FormsAuthentication.FormsCookieName], RequestLifecyclePhase.EndRequest, true); if (preAnalyzer != null) { ComparisonResult result = RequestAnalyzer.Compare(preAnalyzer, postAnalyzer); if (result == ComparisonResult.UnauthenticatedRequest) { // Nothing to do } else if (result == ComparisonResult.AuthenticatedRequest) { // Nothing to do } else if (result == ComparisonResult.LoginRequest) { // Store the ticket on the server string hash = UserAuthentication.CalculateFormsAuthTicketHash(postAnalyzer.FormsAuthenticationTicket); string key = Guid.NewGuid().ToString(); UserAuthenticationTicket userAuthTicket = new UserAuthenticationTicket { Key = key, Username = postAnalyzer.FormsAuthenticationTicket.Name, HostAddress = request.UserHostAddress, CookieDomain = postAnalyzer.FormsAuthenticationCookie.Domain, CookiePath = postAnalyzer.FormsAuthenticationCookie.Path, CookieSecure = postAnalyzer.FormsAuthenticationCookie.Secure, TicketExpiration = postAnalyzer.FormsAuthenticationTicket.Expiration, CookieName = postAnalyzer.FormsAuthenticationCookie.Name, TicketIsPersistent = postAnalyzer.FormsAuthenticationTicket.IsPersistent, TicketIssueDate = postAnalyzer.FormsAuthenticationTicket.IssueDate, TicketUserData = postAnalyzer.FormsAuthenticationTicket.UserData, TicketVersion = postAnalyzer.FormsAuthenticationTicket.Version, TicketHash = hash }; UserAuthentication.Provider.InsertTicket(userAuthTicket, postAnalyzer.FormsAuthenticationTicket.Expiration); FormsAuthenticationTicket newFormsAuthTicket = UserAuthentication.CreateFormsAuthTicket( postAnalyzer.FormsAuthenticationTicket.Name, postAnalyzer.FormsAuthenticationCookie.Path, hash + ";" + key, postAnalyzer.FormsAuthenticationTicket.IssueDate, postAnalyzer.FormsAuthenticationTicket.Expiration, false ); UserAuthentication.ClearAuthCookie(); UserAuthentication.SetAuthCookie(newFormsAuthTicket, true, true); } else if (result == ComparisonResult.LogoutRequest) { if (preAnalyzer.UserAuthenticationTicket != null) { UserAuthentication.Provider.RevokeTicket(preAnalyzer.UserAuthenticationTicket.Key); } UserAuthentication.ClearAuthCookie(); // Revoke the ticket on the server } else if (result == ComparisonResult.MaliciousRequest) { UserAuthentication.ClearAuthCookie(); // Hmm.. what to do // System.Diagnostics.Debugger.Break(); } } } else if (status == FormsAuthenticationStatus.Valid) { // TODO: Handle sliding ticket expiration // UserAuthentication.Provider.UpdateTicketExpiration(); } }
internal void SetServerAuthenticationTicket(UserAuthenticationTicket userAuthenticationTicket) { _userAuthenticationTicket = userAuthenticationTicket; }
/// <summary> /// Perform analysis of the UserAuthenticationTicket supplied /// </summary> /// <param name="contextInformation">Context information derived from the current request</param> /// <param name="cookieAnalysis">The result of the FormsAuthenticationCookie analysis</param> /// <param name="ticketAnalysis">The result of the FormsAuthenticationTicket analysis</param> /// <param name="userAuthenticationTicket">The UserAuthenticationTicket to inspect</param> /// <param name="enforceHostAddressValidation">Indicates whether to enforce that the ticket was provided from the same IP address for which it created</param> /// <returns>A UserAuthenticationTicketAnalysis object containing the results of the analysis</returns> public static UserAuthenticationTicketAnalysis AnalyzeServerAuthenticationTicket(ContextInformation contextInformation, FormsAuthenticationCookieAnalysis cookieAnalysis, FormsAuthenticationTicketAnalysis ticketAnalysis, UserAuthenticationTicket userAuthenticationTicket, bool enforceHostAddressValidation) { UserAuthenticationTicketAnalysis analysis = new UserAuthenticationTicketAnalysis(); HttpCookie formsAuthCookie = cookieAnalysis.FormsAuthenticationCookie; FormsAuthenticationTicket formsAuthTicket = ticketAnalysis.FormsAuthenticationTicket; analysis.TicketExists = (userAuthenticationTicket != null); if (analysis.TicketExists) { analysis.UserAuthenticationTicket = userAuthenticationTicket; if (userAuthenticationTicket != null) { analysis.CookieDomainMatch = (userAuthenticationTicket.CookieDomain == formsAuthCookie.Domain); analysis.CookiePathMatch = (userAuthenticationTicket.CookiePath == formsAuthTicket.CookiePath && formsAuthTicket.CookiePath == formsAuthCookie.Path); analysis.CookieSecureMatch = (userAuthenticationTicket.CookieSecure == formsAuthCookie.Secure); /* analysis.ExpirationMatch = (DateTime.Compare(UserAuthenticationTicket.TicketExpiration, formsAuthTicket.Expiration) == 0 && DateTime.Compare(formsAuthTicket.Expiration, formsAuthCookie.Expires) == 0); */ analysis.CookieNameMatch = (userAuthenticationTicket.CookieName == formsAuthCookie.Name); analysis.TicketPersistenceMatch = (userAuthenticationTicket.TicketIsPersistent == formsAuthTicket.IsPersistent); analysis.TicketIssueDateMatch = (DateTime.Compare(userAuthenticationTicket.TicketIssueDate, formsAuthTicket.IssueDate) == 0); analysis.TicketUsernameMatch = (userAuthenticationTicket.Username == formsAuthTicket.Name); analysis.TicketVersionMatch = (userAuthenticationTicket.TicketVersion == formsAuthTicket.Version); analysis.TicketHashMatch = (userAuthenticationTicket.TicketHash == ticketAnalysis.TicketHash); analysis.HostAddressMatch = (userAuthenticationTicket.HostAddress == contextInformation.HostAddress); } analysis.IsValid = analysis.CookieDomainMatch && analysis.CookiePathMatch && analysis.CookieSecureMatch && /* analysis.ExpirationMatch && */ analysis.CookieNameMatch && analysis.TicketPersistenceMatch && analysis.TicketIssueDateMatch && analysis.TicketUsernameMatch && analysis.TicketVersionMatch && analysis.TicketHashMatch && (!enforceHostAddressValidation || analysis.HostAddressMatch); if (!analysis.IsValid) { analysis.IsMalicious = !analysis.CookieDomainMatch || !analysis.CookiePathMatch || !analysis.CookieSecureMatch || /* !analysis.ExpirationMatch || */ !analysis.CookieNameMatch || !analysis.TicketPersistenceMatch || !analysis.TicketIssueDateMatch || !analysis.TicketUsernameMatch || !analysis.TicketVersionMatch || !analysis.TicketHashMatch || (enforceHostAddressValidation && !analysis.HostAddressMatch); } } else { analysis.IsValid = false; analysis.IsMalicious = false; } return analysis; }
protected void TamperButton_Click(object sender, EventArgs e) { string formsAuthCookieValue = CookieValueServer.Text; FormsAuthenticationTicket newTicket = null; if (TamperFormsAuthenticationTicket.Checked) { newTicket = UserAuthentication.CreateFormsAuthTicket( TicketName.Text, TicketCookiePath.Text, TicketUserDataServer.Text, string.IsNullOrEmpty(TicketIssueDate.Text) ? (DateTime?)null : DateTime.Parse(TicketIssueDate.Text), string.IsNullOrEmpty(TicketExpiration.Text) ? (DateTime?)null : DateTime.Parse(TicketExpiration.Text), TicketIsPersistent.Checked ); formsAuthCookieValue = FormsAuthentication.Encrypt(newTicket); } if (TamperFormsAuthenticationCookie.Checked) { UserAuthentication.ClearAuthCookie(); HttpCookie newCookie = new HttpCookie(FormsAuthentication.FormsCookieName); newCookie.Domain = CookieDomain.Text; newCookie.Path = CookiePath.Text; newCookie.Secure = CookieSecure.Checked; newCookie.HttpOnly = true; DateTime newDate = DateTime.MinValue; if (!string.IsNullOrEmpty(CookieExpires.Text) && DateTime.TryParse(CookieExpires.Text, out newDate)) { newCookie.Expires = newDate; } if (TamperFormsAuthenticationTicket.Checked) { newCookie.Value = formsAuthCookieValue; } else { newCookie.Value = CookieValueServer.Text; } Request.Cookies.Add(newCookie); // Required for validation only Response.Cookies.Add(newCookie); } else if (TamperFormsAuthenticationTicket.Checked) { UserAuthentication.ClearAuthCookie(); HttpCookie newCookie = new HttpCookie(FormsAuthentication.FormsCookieName, formsAuthCookieValue); newCookie.Path = FormsAuthentication.FormsCookiePath; newCookie.Secure = FormsAuthentication.RequireSSL; newCookie.HttpOnly = true; if (FormsAuthentication.CookieDomain != null) { newCookie.Domain = FormsAuthentication.CookieDomain; } if (TicketIsPersistent.Checked) { newCookie.Expires = newTicket.Expiration; } Request.Cookies.Add(newCookie); // Required for validation only Response.Cookies.Add(newCookie); } if (TamperServerAuthenticationTicket.Checked) { string originalKey = Request["OriginalTicketKey"]; string newKey = ServerKey.Text; UserAuthentication.Provider.RevokeTicket(originalKey); UserAuthenticationTicket serverAuthenticationTicket = new UserAuthenticationTicket(); serverAuthenticationTicket.Key = ServerKey.Text; serverAuthenticationTicket.Username = ServerUsername.Text; serverAuthenticationTicket.HostAddress = ServerHostAddress.Text; serverAuthenticationTicket.CookieName = ServerCookieName.Text; serverAuthenticationTicket.CookieDomain = ServerCookieDomain.Text; serverAuthenticationTicket.CookiePath = ServerCookiePath.Text; serverAuthenticationTicket.CookieSecure = ServerCookieSecure.Checked; serverAuthenticationTicket.TicketIsPersistent = ServerTicketIsPersistent.Checked; serverAuthenticationTicket.TicketUserData = ServerTicketUserData.Text; serverAuthenticationTicket.TicketVersion = int.Parse(ServerTicketVersion.Text); serverAuthenticationTicket.TicketHash = ServerTicketHash.Text; DateTime ticketExpiration = DateTime.MinValue; DateTime ticketIssueDate = DateTime.MinValue; if (DateTime.TryParse(ServerTicketExpiration.Text, out ticketExpiration)) { serverAuthenticationTicket.TicketExpiration = ticketExpiration; } if (DateTime.TryParse(ServerTicketIssueDate.Text, out ticketIssueDate)) { serverAuthenticationTicket.TicketIssueDate = ticketIssueDate; } UserAuthentication.Provider.InsertTicket(serverAuthenticationTicket, ticketExpiration); } Response.Redirect(Request.RawUrl, false); // postAnalyzer = new FormsAuthenticationAnalyzer(Request.Cookies[FormsAuthentication.FormsCookieName], true); // BindFields(); // ValidateFields(); }