Simulator.SimulatedLoginAttemptGenerator.BenignLoginAttempt C# (CSharp) Method

BenignLoginAttempt() public method

Get a benign login attempt to simulate
public BenignLoginAttempt ( System.DateTime eventTimeUtc ) : SimulatedLoginAttempt
eventTimeUtc System.DateTime
return SimulatedLoginAttempt
        public SimulatedLoginAttempt BenignLoginAttempt(DateTime eventTimeUtc)
        {
            // If there is a benign login attempt already scheduled to occur by now,
            // send it instaed
            lock (ScheduledBenignAttempts)
            {
                if (ScheduledBenignAttempts.Count > 0 &&
                    ScheduledBenignAttempts.First().TimeOfAttemptUtc < eventTimeUtc)
                {
                    SimulatedLoginAttempt result = ScheduledBenignAttempts.First();
                    ScheduledBenignAttempts.Remove(result);
                    return result;
                }
            }

            string mistake = "";
            //1. Pick a user at random
            SimulatedUserAccount account = _simAccounts.BenignAccountSelector.GetItemByWeightedRandom();

            //2. Deal with cookies
            string cookie;
            // Add a new cookie if there are no cookies, or with if we haven't reached the max number of cookies and lose a roll of the dice
            if (account.Cookies.Count == 0 ||
                (account.Cookies.Count < _experimentalConfiguration.MaxCookiesPerUserAccount && StrongRandomNumberGenerator.GetFraction() > _experimentalConfiguration.ChanceOfCoookieReUse))
            {
                // We'll use the decimal represenation of a 64-bit unsigned integer as our cookie 
                cookie = StrongRandomNumberGenerator.Get64Bits().ToString();
                account.Cookies.Add(cookie);
            }
            else
            {
                // Use one of the user's existing cookies selected at random
                cookie = account.Cookies.ToArray()[(int)StrongRandomNumberGenerator.Get32Bits(account.Cookies.Count)];
            }

            //Console.WriteLine("The user currently has " + account.Cookies.Count + " cookies.  Using: " + cookie);

            //3. Choose an IP address for the login
            // 1/3 of times login with the primary IP address, otherwise, choose an IP randomly from the benign IP pool
            IPAddress clientIp;
            if (account.ClientAddresses.Count == 0 ||
                (account.ClientAddresses.Count < _experimentalConfiguration.MaxIpPerUserAccount && StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfIpReUse))
            {
                // Use a new IP for the user
                account.ClientAddresses.Add(clientIp = _ipPool.GetNewRandomBenignIp());
            }
            else
            {
                // Use one of the user's existing IP Addresses selected at random
                clientIp = account.ClientAddresses.ToArray()[(int)StrongRandomNumberGenerator.Get32Bits(account.ClientAddresses.Count)];
            }
                        
            string password = account.Password;

            //
            // Add benign failures

            // An automated client begins a string of login attempts using an old (stale) password 
            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfLongRepeatOfStalePassword)
            {
                // To cause this client to be out of date, we'll change the password here.
                string newPassword = _simPasswords.GetPasswordFromWeightedDistribution();
                _userAccountController.SetPassword(account, newPassword, account.Password);
                mistake += "StalePassword";

                // Schedule all the future failed attempts a fixed distance aparat
                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    DateTime currentTimeUtc = eventTimeUtc;
                    for (additionalMistakes = 1; additionalMistakes < _experimentalConfiguration.LengthOfLongRepeatOfOldPassword; additionalMistakes++)
                    {
                        currentTimeUtc = currentTimeUtc.AddSeconds(_experimentalConfiguration.MinutesBetweenLongRepeatOfOldPassword);
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                            account, password, false, false, clientIp, cookie, mistake, currentTimeUtc));
                    }
                    for (uint correctLogins = 1; correctLogins < _experimentalConfiguration.LengthOfLongRepeatOfOldPassword; correctLogins++)
                    {
                        currentTimeUtc = currentTimeUtc.AddSeconds(_experimentalConfiguration.MinutesBetweenLongRepeatOfOldPassword);
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                            account, newPassword, false, false, clientIp, cookie, mistake,currentTimeUtc));
                    }
                }
            }

            // The benign user may mistype her password causing a typo 
            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfBenignPasswordTypo)
            {
                mistake += "Typo";
                // Typos tend to come in clusters, and are hopefully followed by a correct login
                // Add additional typos to the schedule of future benign attempts and then a submission of the correct password
                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatTypo)
                    {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                            account, AddTypoToPassword(password), false, false, clientIp, cookie, mistake,
                            eventTimeUtc.AddSeconds(_experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * ++additionalMistakes)));
                    }
                    // Add a correct login after the string of typos
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                        account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                            _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds*(1 + additionalMistakes))));

                }
                // Put the typo into the password for the first typo failure, to be returned by this function.
                password = AddTypoToPassword(password);
            }

            // The benign user may mistakenly use a password for another of her accounts, which we draw from same distribution
            // we used to generate user account passwords
            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfAccidentallyUsingAnotherAccountPassword)
            {
                mistake += "WrongPassword";

                // Choices of the wrong account password may come in clusters, and are hopefully followed by a correct login
                // Add additional typos to the schedule of future benign attempts and then a submission of the correct password
                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while(StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatUseOfPasswordFromAnotherAccount) {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                            account, _simPasswords.GetPasswordFromWeightedDistribution(), false, false, clientIp, cookie,
                            mistake, eventTimeUtc.AddSeconds(_experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds*++additionalMistakes)));
                    }
                    // Add a correct login after mistakes
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                        account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (additionalMistakes+1))));
                }

                // Make the current request have the wrong password
                password = _simPasswords.GetPasswordFromWeightedDistribution();
            }

            // The benign user may mistype her account name, and land on someone else's account name
            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfBenignAccountNameTypoResultingInAValidUserName)
            {
                mistake += "WrongAccountName";

                // Choices of the wrong account password may come in clusters, and are hopefully followed by a correct login
                // Add additional typos to the schedule of future benign attempts and then a submission of the correct password
                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatWrongAccountName)
                    {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                            _simAccounts.GetBenignAccountAtRandomUniform(), password, false, false, clientIp, cookie, mistake, eventTimeUtc.AddSeconds(
                            _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * ++additionalMistakes)));
                    }
                    // Add a correct login after mistakes
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                        account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (additionalMistakes + 1))));

                    // Make the current request have the wrong account name
                    account = _simAccounts.GetBenignAccountAtRandomUniform();
                }
            }

            return new SimulatedLoginAttempt(account, password, false, false, clientIp, cookie, mistake, eventTimeUtc);

        }

Usage Example

Example #1
0
        /// <summary>
        /// Evaluate the accuracy of our stopguessing service by sending user logins and malicious traffic
        /// </summary>
        /// <returns></returns>
        public void Run()
        {
            _logger.WriteStatus("In RunInBackground");

            _logger.WriteStatus("Priming password-tracking with known common passwords");
            _simPasswords.PrimeWithKnownPasswordsAsync(_binomialLadderFilter, 40);
            _logger.WriteStatus("Finished priming password-tracking with known common passwords");

            _logger.WriteStatus("Creating IP Pool");
            _ipPool = new IpPool(_experimentalConfiguration);
            _logger.WriteStatus("Generating simualted account records");
            _simAccounts = new SimulatedAccounts(_ipPool, _simPasswords, _logger);
            _simAccounts.Generate(_experimentalConfiguration);

            _logger.WriteStatus("Creating login-attempt generator");
            _attemptGenerator = new SimulatedLoginAttemptGenerator(_experimentalConfiguration, _simAccounts, _ipPool,
                _simPasswords);
            _logger.WriteStatus("Finiished creating login-attempt generator");


            foreach (
                ConcurrentStreamWriter writer in
                    new[]
                    {_AttackAttemptsWithValidPasswords, _LegitimateAttemptsWithValidPasswords, _OtherAttempts})
            {
                lock (writer)
                {

                    writer.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}" +
                                                   "\t{11}\t{12}\t{13}\t{14}\t{15}\t{16}\t{17}\t{18}\t{19}\t{20}\t{21}\t{22}\t{23}\t{24}\t{25}",
                        "Password",
                        "UserID",
                        "IP",
                        "DeviceCookie",
                        "IsFrequentlyGuessedPw",
                        "IsPasswordCorrect",
                        "IsFromAttackAttacker",
                        "IsAGuess",
                        "IPInOposingPool",
                        "IsClientAProxyIP",
                        "TypeOfMistake",
                        "DecayedInvalidAttemptsPerPassword",
                        "DecayedMaxConsecutiveIncorrectAttemptsPerAccount",
                        "DecayedSuccessfulLogins",
                        "DecayedAccountFailuresInfrequentPassword",
                        "DecayedAccountFailuresFrequentPassword",
                        "DecayedRepeatAccountFailuresInfrequentPassword",
                        "DecayedRepeatAccountFailuresFrequentPassword",
                        "DecayedPasswordFailuresNoTypoInfrequentPassword",
                        "DecayedPasswordFailuresNoTypoFrequentPassword",
                        "DecayedPasswordFailuresTypoInfrequentPassword",
                        "DecayedPasswordFailuresTypoFrequentPassword",
                        "DecayedRepeatPasswordFailuresNoTypoInfrequentPassword",
                        "DecayedRepeatPasswordFailuresNoTypoFrequentPassword",
                        "DecayedRepeatPasswordFailuresTypoInfrequentPassword",
                        "DecayedRepeatPasswordFailuresTypoFrequentPassword"
                        ));
                }
            }

            TimeSpan testTimeSpan = _experimentalConfiguration.TestTimeSpan;
            double ticksBetweenLogins = ((double) testTimeSpan.Ticks)/
                                        (double) _experimentalConfiguration.TotalLoginAttemptsToIssue;
            int interlockedCount = 0;

            Parallel.For(0L, (long) _experimentalConfiguration.TotalLoginAttemptsToIssue, (count, pls) =>
                //) TaskParalllel.RepeatWithWorkers(_experimentalConfiguration.TotalLoginAttemptsToIssue, 
                //async (count, cancelToken) =>
                // (count) => 
            {
                interlockedCount = Interlocked.Add(ref interlockedCount, 1);
                if (interlockedCount % 10000 == 0)
                    _logger.WriteStatus("Login Attempt {0:N0}", interlockedCount);
                DateTime eventTimeUtc = StartTimeUtc.AddTicks((long) (ticksBetweenLogins* interlockedCount));
                SimulatedLoginAttempt simAttempt;
                if (StrongRandomNumberGenerator.GetFraction() <
                    _experimentalConfiguration.FractionOfLoginAttemptsFromAttacker)
                {
                    switch (_experimentalConfiguration.AttackersStrategy)
                    {
                        case ExperimentalConfiguration.AttackStrategy.UseUntilLikelyPopular:
                            simAttempt =
                                _attemptGenerator.MaliciousLoginAttemptBreadthFirstAvoidMakingPopular(eventTimeUtc);
                            break;
                        case ExperimentalConfiguration.AttackStrategy.Weighted:
                            simAttempt = _attemptGenerator.MaliciousLoginAttemptWeighted(eventTimeUtc);
                            break;
                        case ExperimentalConfiguration.AttackStrategy.BreadthFirst:
                        default:
                            simAttempt = _attemptGenerator.MaliciousLoginAttemptBreadthFirst(eventTimeUtc);
                            break;
                    }
                }
                else
                {
                    simAttempt = _attemptGenerator.BenignLoginAttempt(eventTimeUtc);
                }


                // Get information about the client's IP
                SimIpHistory ipHistory = _ipHistoryCache.GetOrAdd(simAttempt.AddressOfClientInitiatingRequest,
                    (ip) => new SimIpHistory(
                            _experimentalConfiguration.BlockingOptions
                                .NumberOfFailuresToTrackForGoingBackInTimeToIdentifyTypos) );
                //SimIpHistory ipHistory = await _ipHistoryCache.GetAsync(simAttempt.AddressOfClientInitiatingRequest, cancelToken);

                double[] scores = ipHistory.GetAllScores(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife,
                    simAttempt.TimeOfAttemptUtc);

                simAttempt.UpdateSimulatorState(this, ipHistory);

                double decayingInvalidPasswordAttempts = 0d;
                if (simAttempt.IsPasswordValid)
                {
                    DecayingDouble incorrectPasswordAttempts;
                    if (_incorrectPasswordCounts.TryGetValue(simAttempt.Password, out incorrectPasswordAttempts))
                        decayingInvalidPasswordAttempts = incorrectPasswordAttempts.GetValue(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc);
                } else
                {
                    decayingInvalidPasswordAttempts = 1d;
                    DecayingDouble incorrectPasswordAttempts;
                    if (_incorrectPasswordCounts.TryGetValue(simAttempt.Password, out incorrectPasswordAttempts))
                        decayingInvalidPasswordAttempts += incorrectPasswordAttempts.GetValue(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc);
                    _incorrectPasswordCounts[simAttempt.Password] = new DecayingDouble(decayingInvalidPasswordAttempts, simAttempt.TimeOfAttemptUtc);
                }

                var ipInfo = _ipPool.GetIpAddressDebugInfo(simAttempt.AddressOfClientInitiatingRequest);
                string outputString = string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\t{12}\t{13}",
                    simAttempt.Password,
                    simAttempt.SimAccount?.UsernameOrAccountId ?? "<null>",
                    simAttempt.AddressOfClientInitiatingRequest,
                    simAttempt.DeviceCookieHadPriorSuccessfulLoginForThisAccount ? "HadCookie" : "NoCookie",
                    simAttempt.IsFrequentlyGuessedPassword ? "Frequent" : "Infrequent",
                    simAttempt.IsPasswordValid ? "Correct" : "Incorrect",
                    simAttempt.IsFromAttacker ? "FromAttacker" : "FromUser",
                    simAttempt.IsGuess ? "IsGuess" : "NotGuess",
                    simAttempt.IsFromAttacker
                        ? (ipInfo.UsedByBenignUsers ? "IsInBenignPool" : "NotUsedByBenign")
                        : (ipInfo.UsedByAttackers ? "IsInAttackersIpPool" : "NotUsedByAttacker"),
                    ipInfo.IsPartOfProxy ? "ProxyIP" : "NotAProxy",
                    string.IsNullOrEmpty(simAttempt.MistakeType) ? "-" : simAttempt.MistakeType,
                    decayingInvalidPasswordAttempts,
                    simAttempt.SimAccount?.MaxConsecutiveIncorrectAttempts.GetValue(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc) ?? 0d,
                    string.Join("\t", scores.Select(s => s.ToString(CultureInfo.InvariantCulture)).ToArray())
                    );

                if (simAttempt.IsFromAttacker && simAttempt.IsPasswordValid)
                {
                    lock (_AttackAttemptsWithValidPasswords)
                    {
                        _AttackAttemptsWithValidPasswords.WriteLine(outputString);
                        //_AttackAttemptsWithValidPasswords.Flush();
                    }
                }
                else if (!simAttempt.IsFromAttacker && simAttempt.IsPasswordValid)
                {
                    lock (_LegitimateAttemptsWithValidPasswords)
                    {
                        _LegitimateAttemptsWithValidPasswords.WriteLine(outputString);
                        //_LegitiamteAttemptsWithValidPasswords.Flush();
                    }
                }
                else
                {
                    lock (_OtherAttempts)
                    {
                        _OtherAttempts.WriteLine(outputString);
                        //_OtherAttempts.Flush();
                    }
                }
            });
            //(e) => {
            //},
            //cancellationToken: cancellationToken).ConfigureAwait(false);

            foreach (
                ConcurrentStreamWriter writer in
                    new []
                    {_AttackAttemptsWithValidPasswords, _LegitimateAttemptsWithValidPasswords, _OtherAttempts})
            {
                writer.Close();
            }
            //_memoryUsageLimiter.Dispose();
        }
All Usage Examples Of Simulator.SimulatedLoginAttemptGenerator::BenignLoginAttempt