예제 #1
0
 internal RequestAnalysis(ContextInformation context, FormsAuthenticationCookieAnalysis formsAuthenticationCookieResult, FormsAuthenticationTicketAnalysis formsAuthenticationTicketResult, UserAuthenticationTicketAnalysis userAuthenticationTicketResult)
 {
     Context = context;
     FormsAuthenticationCookieResult = formsAuthenticationCookieResult;
     FormsAuthenticationTicketResult = formsAuthenticationTicketResult;
     UserAuthenticationTicketResult = userAuthenticationTicketResult;
 }
 /// <summary>
 /// Retrieve and analyze the UserAuthenticationTicket
 /// </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="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, bool enforceHostAddressValidation)
 {
     UserAuthenticationTicket serverAuthTicket = ticketAnalysis.GetServerAuthenticationTicket();
     return AnalyzeServerAuthenticationTicket(contextInformation, cookieAnalysis, ticketAnalysis, serverAuthTicket, enforceHostAddressValidation);
 }
        /// <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;
        }
        /// <summary>
        /// Perform analysis of the FormsAuthenticationTicket supplied
        /// </summary>
        /// <param name="cookieAnalysis">The result of the FormsAuthenticationCookie analysis</param>
        /// <param name="enforceServerAuthenticationTicketValidation">Indicates whether to enforce UserAuthenticationTicket validation</param>
        /// <param name="isEndRequest">Indicates whether the analysis is occurring during the EndRequest phase of the execution pipeline</param>
        /// <returns>A FormsAuthenticationTicketAnalysis object containing the results of the analysis</returns>
        public static FormsAuthenticationTicketAnalysis AnalyzeFormsAuthenticationTicket(FormsAuthenticationCookieAnalysis cookieAnalysis, bool enforceServerAuthenticationTicketValidation, bool isEndRequest)
        {
            FormsAuthenticationTicketAnalysis analysis = new FormsAuthenticationTicketAnalysis();
            FormsAuthenticationTicket ticket = cookieAnalysis.GetFormsAuthenticationTicket();

            analysis.TicketExists = (ticket != null);
            if (analysis.TicketExists)
            {
                if (cookieAnalysis.HasValue && ticket != null)
                {
                    DateTime netFramework2ReleaseDate = new DateTime(2006, 1, 22);

                    analysis.FormsAuthenticationTicket = ticket;
                    analysis.TicketExists = true;
                    analysis.CookiePathMatches = (ticket.CookiePath == FormsAuthentication.FormsCookiePath);
                    analysis.HasUserData = (!string.IsNullOrEmpty(ticket.UserData));
                    analysis.IsExpired = ticket.Expired || ticket.Expiration.CompareTo(DateTime.Now) < 0;
                    analysis.IsIssueDateValid = (ticket.IssueDate.CompareTo(netFramework2ReleaseDate) > 0);
                    analysis.IsNameValid = (!string.IsNullOrEmpty(ticket.Name)); // && ticket.Name == ContextInformation.ThreadCurrentPrincipalIdentityName && ticket.Name == ContextInformation.UserIdentityName);
                    analysis.HasUserData = !string.IsNullOrEmpty(ticket.UserData);

                    analysis.IsPersistenceValid = true; /* TODO: See how to check this in FormsAuthentication */

                    string guid = null;
                    if (ticket.UserData != null && ticket.UserData.Length == UserAuthentication.HashAlgorithmStringLength + UserAuthentication.GuidStringLength + 1 && ticket.UserData[UserAuthentication.HashAlgorithmStringLength] == ';')
                    {
                        string[] parts = ticket.UserData.Split(';');
                        if (parts.Length == 2)
                        {
                            string hash = parts[0];
                            analysis.UserDataContainsHash = true;
                            for (int i = 0; i < hash.Length; i++)
                            {
                                if (!((hash[i] >= 0x30 && hash[i] <= 0x39) /* 0-9 */
                                    /* || (hash[i] >= 0x41 && hash[i] <= 0x46)      A-F   (lowercase only!) */
                                        || (hash[i] >= 0x61 && hash[i] <= 0x66))) /* a-f */
                                {
                                    analysis.UserDataContainsHash = false;
                                    break;
                                }
                            }

                            if (analysis.UserDataContainsHash)
                            {
                                analysis.TicketHash = hash;
                                string actualHash = UserAuthentication.CalculateFormsAuthTicketHash(ticket);
                                analysis.IsUserDataHashValid = (hash == actualHash);
                            }

                            guid = parts[1];
                            try
                            {
                                #pragma warning disable 168
                                Guid testGuidCreation = new Guid(guid);
                                #pragma warning restore 168

                                analysis.ServerKey = parts[1];
                                analysis.UserDataContainsServerAuthenticationTicketKey = true;
                            }
                            catch (FormatException)
                            {
                                analysis.UserDataContainsServerAuthenticationTicketKey = false;
                            }
                            catch (OverflowException)
                            {
                                analysis.UserDataContainsServerAuthenticationTicketKey = false;
                            }
                            catch (ArgumentNullException)
                            {
                                analysis.UserDataContainsServerAuthenticationTicketKey = false;
                            }
                        }
                        else
                        {
                            analysis.UserDataContainsHash = false;
                            analysis.UserDataContainsServerAuthenticationTicketKey = false;
                        }
                    }
                    else
                    {
                        analysis.UserDataContainsHash = false;
                        analysis.UserDataContainsServerAuthenticationTicketKey = false;
                    }

                    if (!string.IsNullOrEmpty(guid))
                    {
                        UserAuthenticationTicket serverAuthenticationTicket = UserAuthentication.Provider.GetTicket(guid);
                        if (serverAuthenticationTicket != null)
                        {
                            analysis.UserDataServerAuthenticationTicketKeyFound = true;
                            analysis.SetServerAuthenticationTicket(serverAuthenticationTicket);
                        }
                        else
                        {
                            analysis.UserDataServerAuthenticationTicketKeyFound = false;
                        }
                    }
                    else
                    {
                        analysis.UserDataServerAuthenticationTicketKeyFound = false;
                    }

                    analysis.IsVersionValid = (ticket.Version == 2);

                    analysis.IsValid =
                        analysis.TicketExists &&
                        analysis.CookiePathMatches &&
                        !analysis.IsExpired &&
                        analysis.IsIssueDateValid &&
                        analysis.IsNameValid &&
                        analysis.IsPersistenceValid &&
                        analysis.IsVersionValid;

                    /*
                        &&
                        (!enforceServerAuthenticationTicketValidation || analysis.HasUserData) &&
                        (!enforceServerAuthenticationTicketValidation || analysis.UserDataContainsHash) &&
                        (!enforceServerAuthenticationTicketValidation || analysis.IsUserDataHashValid) &&
                        (!enforceServerAuthenticationTicketValidation || analysis.UserDataContainsServerAuthenticationTicketKey) &&
                        (!enforceServerAuthenticationTicketValidation || analysis.UserDataServerAuthenticationTicketKeyFound) &&
                        (!enforceServerAuthenticationTicketValidation || UserAuthenticationTicket != null);
                    */

                    if (!analysis.IsValid)
                    {
                        analysis.IsMalicious =
                            !analysis.CookiePathMatches ||
                            !analysis.IsPersistenceValid ||
                            !analysis.IsIssueDateValid ||
                            !analysis.IsNameValid ||
                            !analysis.IsVersionValid;

                        /*
                        if (!analysis.IsMalicious && enforceServerAuthenticationTicketValidation && !isEndRequest)
                        {
                            analysis.IsMalicious =
                                !analysis.HasUserData ||
                                !analysis.UserDataContainsHash ||
                                !analysis.IsUserDataHashValid ||
                                !analysis.UserDataContainsServerAuthenticationTicketKey;
                        }
                        */
                    }
                }
                else
                {
                    analysis.IsValid = false;
                    analysis.IsMalicious = false;
                }
            }
            else
            {
                analysis.IsValid = false;
                analysis.IsMalicious = false;
            }
            return analysis;
        }
        /// <summary>
        /// Perform analysis of the FormsAuthenticationCookie supplied
        /// </summary>
        /// <param name="cookie">The FormsAuthenticationCookie to validate</param>
        /// <returns>A FormsAuthenticationCookieAnalysis object containing the results of the analysis</returns>
        public static FormsAuthenticationCookieAnalysis AnalyzeFormsAuthenticationCookie(HttpCookie cookie)
        {
            FormsAuthenticationCookieAnalysis analysis = new FormsAuthenticationCookieAnalysis { CookieExists = (cookie != null) };

            if (analysis.CookieExists)
            {
                FormsAuthenticationTicket formsAuthenticationTicket = null;

                analysis.FormsAuthenticationCookie = cookie;
                if (cookie != null)
                {
                    analysis.IsCookieFormsAuthCookie = (cookie.Name == FormsAuthentication.FormsCookieName);
                    analysis.IsDomainValid = (cookie.Domain == FormsAuthentication.CookieDomain);
                    analysis.IsExpired = (DateTime.Now.CompareTo(cookie.Expires) > 0 && cookie.Expires.CompareTo(DateTime.MinValue) != 0);
                    analysis.IsPathValid = (cookie.Path == FormsAuthentication.FormsCookiePath);
                    analysis.IsSecureValid = (cookie.Secure == FormsAuthentication.RequireSSL);
                    analysis.HasValue = !string.IsNullOrEmpty(cookie.Value);
                }

                analysis.ValueDecrypts = analysis.HasValue;
                if (analysis.HasValue)
                {
                    try
                    {
                        if (cookie != null && cookie.Value != null)
                        {
                            formsAuthenticationTicket = FormsAuthentication.Decrypt(cookie.Value);

                            if (formsAuthenticationTicket != null)
                            {
                                analysis.ValueDecrypts = true;
                                analysis.SetFormsAuthenticationTicket(formsAuthenticationTicket);
                            }
                        }
                        else
                        {
                            analysis.ValueDecrypts = false;
                        }
                    }
                    catch
                    {
                        analysis.ValueDecrypts = false;
                    }
                }

                analysis.IsValid =
                    analysis.IsCookieFormsAuthCookie &&
                    analysis.IsDomainValid &&
                    !analysis.IsExpired &&
                    analysis.IsPathValid &&
                    analysis.IsSecureValid &&
                    ((analysis.HasValue && analysis.ValueDecrypts && formsAuthenticationTicket != null) || !analysis.HasValue);

                if (!analysis.IsValid)
                {
                    analysis.IsMalicious =
                        !analysis.IsCookieFormsAuthCookie ||
                        !analysis.IsDomainValid ||
                        !analysis.IsPathValid ||
                        (analysis.HasValue && !analysis.ValueDecrypts) ||
                        !analysis.IsSecureValid;
                }
            }
            else
            {
                analysis.IsValid = false;
                analysis.IsMalicious = false;
            }

            return analysis;
        }