public async Task LoginWithIpWithBadReputationParallelLoadAsync() { TestConfiguration configuration = InitTest(); string[] usernames = CreateUserAccounts(configuration, 250); CreateTestAccount(configuration, Username1, Password1); await TaskParalllel.ForEachWithWorkers(usernames.Skip(20), async (username, itemNumber, cancelToken) => await AuthenticateAsync(configuration, username, Password1, clientAddress: AttackersIp, cancellationToken: cancelToken)); Thread.Sleep(2000); LoginAttempt firstAttackersAttempt = await AuthenticateAsync(configuration, Username1, Password1, clientAddress : AttackersIp); Assert.Equal(AuthenticationOutcome.CredentialsValidButBlocked, firstAttackersAttempt.Outcome); foreach (string username in usernames.Skip(1).Take(19)) { await AuthenticateAsync(configuration, username, Password1, AnotherAttackersIp); } await AuthenticateAsync(configuration, usernames[0], Password1, AnotherAttackersIp); LoginAttempt anotherAttackersAttempt = await AuthenticateAsync(configuration, Username1, Password1, clientAddress : AnotherAttackersIp); Assert.Equal(AuthenticationOutcome.CredentialsValidButBlocked, anotherAttackersAttempt.Outcome); }
public async Task LoginWithIpWithBadReputationParallelLoadAsync() { TestConfiguration configuration = InitTest(); //((MemoryOnlyStableStore) configuration.StableStore).Accounts = null; string[] usernames = CreateUserAccounts(configuration, 250); CreateTestAccount(configuration, Username1, Password1); // Have one attacker make the password popular by attempting to login to every account with it. await TaskParalllel.ForEachWithWorkers(usernames.Skip(20), async (username, itemNumber, cancelToken) => await AuthenticateAsync(configuration, username, Password1, clientAddress: AttackersIp, cancellationToken: cancelToken)); Thread.Sleep(2000); LoginAttempt firstAttackersAttempt = await AuthenticateAsync(configuration, Username1, Password1, clientAddress : AttackersIp); Assert.Equal(AuthenticationOutcome.CredentialsValidButBlocked, firstAttackersAttempt.Outcome); // Now the second attacker should be flagged after using that password 10 times on different accounts. foreach (string username in usernames.Skip(1).Take(19)) { await AuthenticateAsync(configuration, username, Password1, AnotherAttackersIp); } await AuthenticateAsync(configuration, usernames[0], Password1, AnotherAttackersIp); LoginAttempt anotherAttackersAttempt = await AuthenticateAsync(configuration, Username1, Password1, clientAddress : AnotherAttackersIp); Assert.Equal(AuthenticationOutcome.CredentialsValidButBlocked, anotherAttackersAttempt.Outcome); }
/// <summary> /// Evaluate the accuracy of our stopguessing service by sending user logins and malicious traffic /// </summary> /// <returns></returns> public async Task Run(CancellationToken cancellationToken = default(CancellationToken)) { _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); await _simAccounts.GenerateAsync(_experimentalConfiguration, cancellationToken); _logger.WriteStatus("Creating login-attempt generator"); _attemptGenerator = new SimulatedLoginAttemptGenerator(_experimentalConfiguration, _simAccounts, _ipPool, _simPasswords); _logger.WriteStatus("Finiished creating login-attempt generator"); foreach (TextWriter writer in new TextWriter[] { _AttackAttemptsWithValidPasswords, _LegitiamteAttemptsWithValidPasswords, _OtherAttempts }) { writer.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}", //,{9} "Password", "UserID", "IP", "IsFrequentlyGuessedPw", "IsPasswordCorrect", "IsFromAttackAttacker", "IsAGuess", "IPInOposingPool", "IsClientAProxyIP", "TypeOfMistake" //string.Join(",") ); } TimeSpan testTimeSpan = _experimentalConfiguration.TestTimeSpan; double ticksBetweenLogins = ((double)testTimeSpan.Ticks) / (double)_experimentalConfiguration.TotalLoginAttemptsToIssue; await TaskParalllel.RepeatWithWorkers(_experimentalConfiguration.TotalLoginAttemptsToIssue, async (count, cancelToken) => { if (count % 10000 == 0) { _logger.WriteStatus("Login Attempt {0:N0}", count); } DateTime eventTimeUtc = StartTimeUtc.AddTicks((long)(ticksBetweenLogins *count)); 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 = await _ipHistoryCache.GetAsync(simAttempt.AddressOfClientInitiatingRequest, cancelToken); double[] scores = ipHistory.GetAllScores(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc); simAttempt.UpdateSimulatorState(this, ipHistory); var ipInfo = _ipPool.GetIpAddressDebugInfo(simAttempt.AddressOfClientInitiatingRequest); string outputString = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}", simAttempt.Password, simAttempt.SimAccount?.UsernameOrAccountId ?? "<null>", simAttempt.AddressOfClientInitiatingRequest, 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, string.Join(",", scores.Select(s => s.ToString(CultureInfo.InvariantCulture)).ToArray()) ); if (simAttempt.IsFromAttacker && simAttempt.IsPasswordValid) { await _AttackAttemptsWithValidPasswords.WriteLineAsync(outputString); await _AttackAttemptsWithValidPasswords.FlushAsync(); } else if (!simAttempt.IsFromAttacker && simAttempt.IsPasswordValid) { await _LegitiamteAttemptsWithValidPasswords.WriteLineAsync(outputString); await _LegitiamteAttemptsWithValidPasswords.FlushAsync(); } else { await _OtherAttempts.WriteLineAsync(outputString); await _OtherAttempts.FlushAsync(); } }, //(e) => { //}, cancellationToken : cancellationToken); _memoryUsageLimiter.Dispose(); }