コード例 #1
0
        /// <summary>
        /// Add a typo to a password for simulating user typo errors
        /// </summary>
        /// <param name="originalPassword">The original password to add a typo to</param>
        /// <returns>The password modified to contain a typo</returns>
        public static string AddTypoToPassword(string originalPassword)
        {
            // Adding a character will meet the edit distance def. of typo, though if simulating systems that weigh
            // different typos differently one might want to create a variety of typos here
            const string typoAlphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";

            return(originalPassword + typoAlphabet[(int)StrongRandomNumberGenerator.Get32Bits(typoAlphabet.Length)]);
        }
コード例 #2
0
        public SimulatedLoginAttempt MaliciousAttemptToSantiizeIpViaAValidLogin(IPAddress ipAddressToSanitizeThroughLogin)
        {
            SimulatedUserAccount simAccount = _simAccounts.GetMaliciousAccountAtRandomUniform();

            return(new SimulatedLoginAttempt(simAccount, simAccount.Password,
                                             true, false,
                                             ipAddressToSanitizeThroughLogin, StrongRandomNumberGenerator.Get64Bits().ToString(), "",
                                             DateTime.UtcNow));
        }
コード例 #3
0
        protected int GetIndexOfRandomBitOfDesiredValue(bool desiredValueOfElement)
        {
            int elementIndex;

            do
            {
                elementIndex = (int)(StrongRandomNumberGenerator.Get64Bits((ulong)base.Length));
            } while (base[elementIndex] != desiredValueOfElement);

            return(elementIndex);
        }
コード例 #4
0
        protected int GetIndexOfRandomBitOfDesiredValue(bool desiredValueOfElement)
        {
            int elementIndex;

            // Iterate through random elements until we find one that is set to one (true) and can be cleared
            do
            {
                elementIndex = (int)(StrongRandomNumberGenerator.Get64Bits((ulong)base.Length));
            } while (base[elementIndex] != desiredValueOfElement);

            return(elementIndex);
        }
コード例 #5
0
        public int Step(string key, int?heightOfLadderInRungs = null)
        {
            List <int> rungs      = GetIndexesAssociatedWithAnElement(key, heightOfLadderInRungs).ToList();
            List <int> rungsAbove = rungs.Where(rung => !base[rung]).ToList();

            int indexOfElementToSet = (rungsAbove.Count > 0) ?
                                      rungsAbove[(int)(StrongRandomNumberGenerator.Get32Bits((uint)rungsAbove.Count))] :
                                      GetIndexOfRandomBitOfDesiredValue(false);

            int indexOfElementToClear = GetIndexOfRandomBitOfDesiredValue(true);

            SwapBits(indexOfElementToSet, indexOfElementToClear);

            return(rungs.Count - rungsAbove.Count);
        }
コード例 #6
0
        public SimulatedLoginAttempt MaliciousLoginAttemptWeighted(DateTime eventTimeUtc)
        {
            SimulatedUserAccount targetBenignAccount =
                (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ProbabilityThatAttackerChoosesAnInvalidAccount)
                    ? null : _simAccounts.GetBenignAccountAtRandomUniform();

            return(new SimulatedLoginAttempt(
                       targetBenignAccount,
                       _simPasswords.GetPasswordFromWeightedDistribution(),
                       true, true,
                       _ipPool.GetRandomMaliciousIp(),
                       StrongRandomNumberGenerator.Get64Bits().ToString(),
                       "",
                       eventTimeUtc));
        }
コード例 #7
0
        public static double GetNormal()
        {
            double v1;
            double s;

            do
            {
                v1 = 2.0 * StrongRandomNumberGenerator.GetFraction() - 1.0;
                double v2 = 2.0 * StrongRandomNumberGenerator.GetFraction() - 1.0;
                s = v1 * v1 + v2 * v2;
            } while (s >= 1d || s <= 0d);

            s = Math.Sqrt((-2.0 * Math.Log(s)) / s);
            return(v1 * s);
        }
コード例 #8
0
        public async Task CookieUsedInPriorLoginAsync()
        {
            Init();
            string        username          = "******";
            string        password          = "******";
            DbUserAccount account           = userAccountController.Create(username, password);
            string        randomCookiesHash = Convert.ToBase64String(StrongRandomNumberGenerator.GetBytes(16));
            bool          cookieAlreadyPresentOnFirstTest = await
                                                            userAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBeforeAsync(account, randomCookiesHash);

            Assert.False(cookieAlreadyPresentOnFirstTest);
            await userAccountController.RecordHashOfDeviceCookieUsedDuringSuccessfulLoginAsync(account, randomCookiesHash);

            bool cookieAlreadyPresentOnSecondTest = await
                                                    userAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBeforeAsync(account, randomCookiesHash);

            Assert.True(cookieAlreadyPresentOnSecondTest);
        }
コード例 #9
0
        public async Task AddIncorrectPhase2HashAsync()
        {
            Init();
            string        username = "******";
            string        password = "******";
            DbUserAccount account  = userAccountController.Create(username, password);
            string        incorrectPasswordHash = Convert.ToBase64String(StrongRandomNumberGenerator.GetBytes(16));
            bool          incorrectPasswordAlreadyPresentOnFirstTest = await
                                                                       userAccountController.AddIncorrectPhaseTwoHashAsync(account, incorrectPasswordHash);

            Assert.False(incorrectPasswordAlreadyPresentOnFirstTest);
            // Since the hash is added via a background task to minimize response latency, we'll want to
            // wait to be sure it's added
            Thread.Sleep(1000);
            bool incorrectPasswordPresentOnSecondTest = await
                                                        userAccountController.AddIncorrectPhaseTwoHashAsync(account, incorrectPasswordHash);

            Assert.True(incorrectPasswordPresentOnSecondTest);
        }
コード例 #10
0
 public SimulatedLoginAttempt(SimulatedUserAccount account,
                              string password,
                              bool isFromAttacker,
                              bool isGuess,
                              IPAddress clientAddress,
                              string cookieProvidedByBrowser,
                              string mistakeType,
                              DateTime eventTimeUtc
                              )
 {
     SimAccount          = account;
     UserNameOrAccountId = account != null ? account.UsernameOrAccountId : StrongRandomNumberGenerator.Get64Bits().ToString();
     IsPasswordValid     = account != null && account.Password == password;
     AddressOfClientInitiatingRequest = clientAddress;
     TimeOfAttemptUtc        = eventTimeUtc;
     CookieProvidedByBrowser = cookieProvidedByBrowser;
     Password       = password;
     IsFromAttacker = isFromAttacker;
     IsGuess        = isGuess;
     MistakeType    = mistakeType;
 }
コード例 #11
0
        /// <summary>
        /// When one Adds an element to a binomial sketch, a random bit among the subset of k that are currently 0 (false)
        /// will be set to 1 (true).
        /// To ensure roughly half the bits remain zero at all times, a random index from the subset of all k bits that
        /// are currently 1 (true) will be set to 0 (false).
        /// </summary>
        /// <param name="key">The element to add to the set.</param>
        /// <param name="heightOfLadderInRungs">Set if using a ladder shorter than the default for this sketch</param>
        /// <returns>Of the bits at the indices for the given element, the number of bits that were set to 1 (true)
        /// before the Step operation.  The maximum possible value to be returned, if all bits were already
        /// set to 1 (true) would be MaxLadderHeightInRungs.  If an element has not been seen before, the expected (average)
        /// result is MaxLadderHeightInRungs/2, but will vary with the binomial distribution.</returns>
        public int Step(string key, int?heightOfLadderInRungs = null)
        {
            // Get the set of rungs
            List <int> rungs = GetIndexesAssociatedWithAnElement(key, heightOfLadderInRungs).ToList();
            // Select the subset of rungs that have value zero (that are above the element in the ladder)
            List <int> rungsAbove = rungs.Where(rung => !base[rung]).ToList();

            // Identify an element of the array to set
            int indexOfElementToSet = (rungsAbove.Count > 0) ?
                                      // If there are rungs with value value zero/false (rungs above the element), pick one at random
                                      rungsAbove[(int)(StrongRandomNumberGenerator.Get32Bits((uint)rungsAbove.Count))] :
                                      // otherwise, pick an element with value zero/false from the entire array
                                      GetIndexOfRandomBitOfDesiredValue(false);

            // Identify an index to clear from the entire array (selected from those elements with value 1/true)
            int indexOfElementToClear = GetIndexOfRandomBitOfDesiredValue(true);

            // Swap the values of element to be set with the element to be cleared
            SwapBits(indexOfElementToSet, indexOfElementToClear);

            // Return the height of the ladder before the step
            return(rungs.Count - rungsAbove.Count);
        }
コード例 #12
0
        public FilterArray(int numberOfBitsInArray, int maximumBitIndexesPerElement, bool initilizeBitsOfArrayAtRandom,
                           string saltForHashFunctions = "")
        {
            int capacityInBytes = (numberOfBitsInArray + 7) / 8;

            HashFunctionsMappingElementsToBitsInTheArray = new UniversalHashFunction[maximumBitIndexesPerElement];
            for (int i = 0; i < HashFunctionsMappingElementsToBitsInTheArray.Length; i++)
            {
                HashFunctionsMappingElementsToBitsInTheArray[i] =
                    new UniversalHashFunction(i + ":" + saltForHashFunctions, 64);
            }

            if (initilizeBitsOfArrayAtRandom)
            {
                byte[] initialBitValues = new byte[capacityInBytes];
                StrongRandomNumberGenerator.GetBytes(initialBitValues);
                BitArray = new BitArray(initialBitValues);
            }
            else
            {
                BitArray = new BitArray(capacityInBytes * 8);
            }
        }
コード例 #13
0
ファイル: IPPool.cs プロジェクト: szm88891/StopGuessing
        /// <summary>
        /// Get a new IP address for use in a benign request
        /// </summary>
        /// <returns>An IP address</returns>
        public IPAddress GetNewRandomBenignIp()
        {
            IpAddressDebugInfo debugInfo;

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.FractionOfBenignIPsBehindProxies)
            {
                // Use a proxy IP address
                lock (_proxyAddressLock)
                {
                    if (_currentProxyAddress == null || ++_numberOfClientsBehindTheCurrentProxy >=
                        _experimentalConfiguration.ProxySizeInUniqueClientIPs)
                    {
                        // Create a new proxy IP address
                        _currentProxyAddress                  = new IPAddress(StrongRandomNumberGenerator.Get32Bits());
                        debugInfo                             = GetIpAddressDebugInfo(_currentProxyAddress);
                        debugInfo.IsPartOfProxy               = true;
                        debugInfo.UsedByBenignUsers           = true;
                        _numberOfClientsBehindTheCurrentProxy = 0;
                        return(_currentProxyAddress);
                    }
                    else
                    {
                        // Use the most recent proxy IP
                        return(_currentProxyAddress);
                    }
                }
            }
            else
            {
                // Just pick a random address
                IPAddress address = new IPAddress(StrongRandomNumberGenerator.Get32Bits());
                _ipAddresssesInUseByBenignUsers.Add(address);
                debugInfo = GetIpAddressDebugInfo(address);
                debugInfo.UsedByBenignUsers = true;
                return(address);
            }
        }
コード例 #14
0
 public int GetRandomShardIndex()
 {
     return((int)StrongRandomNumberGenerator.Get32Bits(NumberOfShards));
 }
コード例 #15
0
        /// <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();
        }
コード例 #16
0
ファイル: Simulator.cs プロジェクト: szm88891/StopGuessing
        /// <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();
        }
コード例 #17
0
        /// <summary>
        /// Get a benign login attempt to simulate
        /// </summary>
        /// <returns></returns>
        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));
        }
コード例 #18
0
 /// <summary>
 /// Clear a randomly-selected bit of the filter array to zero.
 /// </summary>
 public void ClearRandomBitToZero()
 {
     ClearBitToZero((int)StrongRandomNumberGenerator.Get32Bits((uint)BitArray.Length));
 }
コード例 #19
0
 /// <summary>
 /// Set a randomly-selected bit of the filter array to one.
 /// </summary>
 public void SetRandomBitToOne()
 {
     SetBitToOne((int)StrongRandomNumberGenerator.Get32Bits((uint)BitArray.Length));
 }
コード例 #20
0
        /// <summary>
        /// Create accounts, generating passwords, primary IP
        /// </summary>
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        public async Task GenerateAsync(ExperimentalConfiguration experimentalConfiguration,
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
                               //IUserAccountContextFactory accountContextFactory,
                                        CancellationToken cancellationToken = default(CancellationToken))
        {
            _logger.WriteStatus("Creating {0:N0} benign accounts", experimentalConfiguration.NumberOfBenignAccounts);
            MemoryUserAccountController          userAccountController     = new MemoryUserAccountController();;
            ConcurrentBag <SimulatedUserAccount> benignSimulatedAccountBag = new ConcurrentBag <SimulatedUserAccount>();

            //
            // Create benign accounts in parallel
            Parallel.For(0, (int)experimentalConfiguration.NumberOfBenignAccounts, (index) =>
            {
                if (index > 0 && index % 10000 == 0)
                {
                    _logger.WriteStatus("Created {0:N0} benign accounts", index);
                }
                SimulatedUserAccount userAccount = new SimulatedUserAccount()
                {
                    UsernameOrAccountId = "user_" + index.ToString(),
                    Password            = _simPasswords.GetPasswordFromWeightedDistribution()
                };
                userAccount.ClientAddresses.Add(_ipPool.GetNewRandomBenignIp());
                userAccount.Cookies.Add(StrongRandomNumberGenerator.Get64Bits().ToString());

                benignSimulatedAccountBag.Add(userAccount);

                double inverseFrequency = Distributions.GetLogNormal(0, 1);
                if (inverseFrequency < 0.01d)
                {
                    inverseFrequency = 0.01d;
                }
                if (inverseFrequency > 50d)
                {
                    inverseFrequency = 50d;
                }
                double frequency = 1 / inverseFrequency;
                lock (BenignAccountSelector)
                {
                    BenignAccountSelector.AddItem(userAccount, frequency);
                }
            });
            BenignAccounts = benignSimulatedAccountBag.ToList();
            _logger.WriteStatus("Finished creating {0:N0} benign accounts",
                                experimentalConfiguration.NumberOfBenignAccounts);

            //
            // Right after creating benign accounts we create IPs and accounts controlled by the attacker.
            // (We create the attacker IPs here, and not earlier, because we need to have the benign IPs generated in order to create overlap)
            _logger.WriteStatus("Creating attacker IPs");
            _ipPool.GenerateAttackersIps();

            _logger.WriteStatus("Creating {0:N0} attacker accounts",
                                experimentalConfiguration.NumberOfAttackerControlledAccounts);
            ConcurrentBag <SimulatedUserAccount> maliciousSimulatedAccountBag = new ConcurrentBag <SimulatedUserAccount>();

            //
            // Create accounts in parallel
            Parallel.For(0, (int)experimentalConfiguration.NumberOfAttackerControlledAccounts, (index) =>
            {
                SimulatedUserAccount userAccount = new SimulatedUserAccount()
                {
                    UsernameOrAccountId = "attacker_" + index.ToString(),
                    Password            = _simPasswords.GetPasswordFromWeightedDistribution(),
                };
                userAccount.ClientAddresses.Add(_ipPool.GetRandomMaliciousIp());
                maliciousSimulatedAccountBag.Add(userAccount);
            });
            AttackerAccounts = maliciousSimulatedAccountBag.ToList();
            _logger.WriteStatus("Finished creating {0:N0} attacker accounts",
                                experimentalConfiguration.NumberOfAttackerControlledAccounts);

            //
            // Now create full UserAccount records for each simulated account and store them into the account context
            Parallel.ForEach(BenignAccounts.Union(AttackerAccounts),
                             (simAccount, loopState) =>
            {
                //if (loopState. % 10000 == 0)
                //    _logger.WriteStatus("Created account {0:N0}", index);
                simAccount.CreditHalfLife = experimentalConfiguration.BlockingOptions.AccountCreditLimitHalfLife;
                simAccount.CreditLimit    = experimentalConfiguration.BlockingOptions.AccountCreditLimit;

                foreach (string cookie in simAccount.Cookies)
                {
                    userAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBeforeAsync(
                        simAccount,
                        LoginAttempt.HashCookie(cookie),
                        cancellationToken);
                }
            });
            _logger.WriteStatus("Finished creating user accounts for each simluated account record");
        }
コード例 #21
0
 public SimulatedUserAccount GetMaliciousAccountAtRandomUniform()
 {
     return(AttackerAccounts[(int)StrongRandomNumberGenerator.Get32Bits(AttackerAccounts.Count)]);
 }
コード例 #22
0
 public SimulatedUserAccount GetBenignAccountAtRandomUniform()
 {
     return(BenignAccounts[(int)StrongRandomNumberGenerator.Get32Bits(BenignAccounts.Count)]);
 }
コード例 #23
0
        public void Generate(ExperimentalConfiguration experimentalConfiguration)
        {
            SimulatedUserAccountController simUserAccountController = new SimulatedUserAccountController();

            _logger.WriteStatus("Creating accounts");
            ConcurrentBag <SimulatedUserAccount> benignSimulatedAccountBag = new ConcurrentBag <SimulatedUserAccount>();

            Parallel.For(0, (int)experimentalConfiguration.NumberOfBenignAccounts, (index) =>
            {
                //if (index > 0 && index % 10000 == 0)
                //    _logger.WriteStatus("Created {0:N0} benign accounts", index);
                SimulatedUserAccount userAccount = simUserAccountController.Create(
                    "user_" + index.ToString(),
                    _simPasswords.GetPasswordFromWeightedDistribution()
                    );
                userAccount.ClientAddresses.Add(_ipPool.GetNewRandomBenignIp());
                string initialCookie = StrongRandomNumberGenerator.Get64Bits().ToString();
                userAccount.Cookies.Add(initialCookie);
                userAccount.HashesOfCookiesOfClientsThatHaveSuccessfullyLoggedIntoThisAccount[initialCookie] = true;

                benignSimulatedAccountBag.Add(userAccount);

                double inverseFrequency = Distributions.GetLogNormal(0, 1);
                if (inverseFrequency < 0.01d)
                {
                    inverseFrequency = 0.01d;
                }
                if (inverseFrequency > 50d)
                {
                    inverseFrequency = 50d;
                }
                double frequency = 1 / inverseFrequency;
                lock (BenignAccountSelector)
                {
                    BenignAccountSelector.AddItem(userAccount, frequency);
                }
            });
            BenignAccounts = benignSimulatedAccountBag.ToList();
            // _logger.WriteStatus("Finished creating {0:N0} benign accounts",
            //     experimentalConfiguration.NumberOfBenignAccounts);

            //_logger.WriteStatus("Creating attacker IPs");
            _ipPool.GenerateAttackersIps();

            //_logger.WriteStatus("Creating {0:N0} attacker accounts",
            //    experimentalConfiguration.NumberOfAttackerControlledAccounts);
            ConcurrentBag <SimulatedUserAccount> maliciousSimulatedAccountBag = new ConcurrentBag <SimulatedUserAccount>();

            Parallel.For(0, (int)experimentalConfiguration.NumberOfAttackerControlledAccounts, (index) =>
            {
                SimulatedUserAccount userAccount = simUserAccountController.Create(
                    "attacker_" + index.ToString(),
                    _simPasswords.GetPasswordFromWeightedDistribution());

                userAccount.ClientAddresses.Add(_ipPool.GetRandomMaliciousIp());
                maliciousSimulatedAccountBag.Add(userAccount);
            });
            AttackerAccounts = maliciousSimulatedAccountBag.ToList();
            _logger.WriteStatus("Finished creating accounts",
                                experimentalConfiguration.NumberOfAttackerControlledAccounts);

            Parallel.ForEach(BenignAccounts.Union(AttackerAccounts),
                             (simAccount, loopState) =>
            {
                simAccount.CreditHalfLife = experimentalConfiguration.BlockingOptions.AccountCreditLimitHalfLife;
                simAccount.CreditLimit    = experimentalConfiguration.BlockingOptions.AccountCreditLimit;

                foreach (string cookie in simAccount.Cookies)
                {
                    simUserAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBefore(
                        simAccount,
                        LoginAttempt.HashCookie(cookie));
                }
            });
            //_logger.WriteStatus("Finished creating user accounts for each simluated account record");
        }
コード例 #24
0
 /// <summary>
 /// Assign the value of either zero or one to a randomly-selected bit of the filter array.
 /// </summary>
 /// <param name="value">The value to be assigned.  Passing 0 causes a value 0 (false) to be stored
 /// and passing any other value causes a one (true) to be stored in the randomly-selected bit.</param>
 public void AssignRandomBit(int value)
 {
     AssignBit((int)StrongRandomNumberGenerator.Get32Bits((uint)BitArray.Length), value != 0);
 }
コード例 #25
0
        public static string AddTypoToPassword(string originalPassword)
        {
            const string typoAlphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";

            return(originalPassword + typoAlphabet[(int)StrongRandomNumberGenerator.Get32Bits(typoAlphabet.Length)]);
        }
コード例 #26
0
        public SimulatedLoginAttempt BenignLoginAttempt(DateTime eventTimeUtc)
        {
            lock (ScheduledBenignAttempts)
            {
                if (ScheduledBenignAttempts.Count > 0 &&
                    ScheduledBenignAttempts.First().TimeOfAttemptUtc < eventTimeUtc)
                {
                    SimulatedLoginAttempt result = ScheduledBenignAttempts.First();
                    ScheduledBenignAttempts.Remove(result);
                    return(result);
                }
            }

            string mistake = "";
            SimulatedUserAccount account = _simAccounts.BenignAccountSelector.GetItemByWeightedRandom();

            string cookie;

            if (account.Cookies.Count == 0 ||
                (account.Cookies.Count < _experimentalConfiguration.MaxCookiesPerUserAccount && StrongRandomNumberGenerator.GetFraction() > _experimentalConfiguration.ChanceOfCoookieReUse))
            {
                cookie = StrongRandomNumberGenerator.Get64Bits().ToString();
                account.Cookies.Add(cookie);
            }
            else
            {
                cookie = account.Cookies.ToArray()[(int)StrongRandomNumberGenerator.Get32Bits(account.Cookies.Count)];
            }

            IPAddress clientIp;

            if (account.ClientAddresses.Count == 0 ||
                (account.ClientAddresses.Count < _experimentalConfiguration.MaxIpPerUserAccount && StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfIpReUse))
            {
                account.ClientAddresses.Add(clientIp = _ipPool.GetNewRandomBenignIp());
            }
            else
            {
                clientIp = account.ClientAddresses.ToArray()[(int)StrongRandomNumberGenerator.Get32Bits(account.ClientAddresses.Count)];
            }

            string password = account.Password;

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfLongRepeatOfStalePassword)
            {
                string newPassword = _simPasswords.GetPasswordFromWeightedDistribution();
                _userAccountController.SetPassword(account, newPassword, account.Password);
                mistake += "StalePassword";

                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));
                    }
                }
            }

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfBenignPasswordTypo)
            {
                mistake += "Typo";
                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)));
                    }
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (1 + additionalMistakes))));
                }
                password = AddTypoToPassword(password);
            }

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfAccidentallyUsingAnotherAccountPassword)
            {
                mistake += "WrongPassword";

                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)));
                    }
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (additionalMistakes + 1))));
                }

                password = _simPasswords.GetPasswordFromWeightedDistribution();
            }

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfBenignAccountNameTypoResultingInAValidUserName)
            {
                mistake += "WrongAccountName";

                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)));
                    }
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (additionalMistakes + 1))));

                    account = _simAccounts.GetBenignAccountAtRandomUniform();
                }
            }

            return(new SimulatedLoginAttempt(account, password, false, false, clientIp, cookie, mistake, eventTimeUtc));
        }
コード例 #27
0
        public async Task RunAsync()
        {
            _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");

            FricSimulator fri = new FricSimulator();

            _logger.WriteStatus("   ");
            _logger.WriteStatus("   ");
            _logger.WriteStatus("Click Enter To First Testing Step");
            _logger.WriteStatus("   ");
            _logger.WriteStatus("   ");
            Console.Read();

            await fri.RunAsync(_logger, _ipPool);

            _logger.WriteStatus("   ");
            _logger.WriteStatus("   ");
            _logger.WriteStatus("Click Enter To Second Testing Step");
            _logger.WriteStatus("   ");
            _logger.WriteStatus("   ");
            Console.Read();
            Console.Read();

            _logger.WriteStatus("Running Password File to check");
            _logger.WriteStatus("   ");

            foreach (
                ConcurrentStreamWriter writer in
                new[]
                { _Attempts })
            {
                lock (writer)
                {
                    writer.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
                                                   "UserID",
                                                   "IP",
                                                   "IsFrequentlyGuessedPw",
                                                   "IsPasswordCorrect",
                                                   "IsFromAttackAttacker",
                                                   "IsAGuess"
                                                   ));
                }
            }

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

            _experimentalConfiguration.TotalLoginAttemptsToIssue = 30000;
            int interlockedCount = 0;

            Parallel.For(0L, (long)_experimentalConfiguration.TotalLoginAttemptsToIssue, (count, pls) =>
            {
                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);
                }


                SimIpHistory ipHistory = _ipHistoryCache.GetOrAdd(simAttempt.AddressOfClientInitiatingRequest,
                                                                  (ip) => new SimIpHistory(
                                                                      _experimentalConfiguration.BlockingOptions
                                                                      .NumberOfFailuresToTrackForGoingBackInTimeToIdentifyTypos));
                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}",
                                                    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,
                                                    decayingInvalidPasswordAttempts,
                                                    simAttempt.SimAccount?.MaxConsecutiveIncorrectAttempts.GetValue(_experimentalConfiguration.BlockingOptions.BlockScoreHalfLife, simAttempt.TimeOfAttemptUtc) ?? 0d,
                                                    string.Join("\t", scores.Select(s => s.ToString(CultureInfo.InvariantCulture)).ToArray())
                                                    );


                _Attempts.WriteLine(outputString);
                _logger.WriteStatus(outputString);
                Thread.Sleep(1300);
            });
            foreach (
                ConcurrentStreamWriter writer in
                new[]
                { _Attempts })
            {
                writer.Close();
            }
        }