/// <summary> /// The attempt generator needs to know about the experimental configuration and have access to the sets of simulated accounts, /// IP addresses, and simulated passwords. /// </summary> /// <param name="experimentalConfiguration"></param> /// <param name="simAccounts"></param> /// <param name="ipPool"></param> /// <param name="simPasswords"></param> public SimulatedLoginAttemptGenerator(ExperimentalConfiguration experimentalConfiguration, SimulatedAccounts simAccounts, IpPool ipPool, SimulatedPasswords simPasswords) { _simAccounts = simAccounts; _experimentalConfiguration = experimentalConfiguration; _ipPool = ipPool; _simPasswords = simPasswords; }
//public void ReduceMemoryUsage(object sender, MemoryUsageLimiter.ReduceMemoryUsageEventParameters parameters) //{ //_ipHistoryCache.RecoverSpace(parameters.FractionOfMemoryToTryToRemove); //} public Simulator(DebugLogger logger, string path, ExperimentalConfiguration myExperimentalConfiguration, SimulatedPasswords simPasswords) { _simPasswords = simPasswords; _logger = logger; _AttackAttemptsWithValidPasswords = //System.IO.TextWriter.Synchronized new ConcurrentStreamWriter(path + "AttackAttemptsWithValidPasswords.txt"); //(new StreamWriter(new FileStream(path + "AttackAttemptsWithValidPasswords.txt", FileMode.CreateNew, FileAccess.Write))); _LegitimateAttemptsWithValidPasswords = //System.IO.TextWriter.Synchronized new ConcurrentStreamWriter(path + "LegitimateAttemptsWithValidPasswords.txt"); //(new StreamWriter(new FileStream(path + "LegitiamteAttemptsWithValidPasswords.txt", FileMode.CreateNew, FileAccess.Write))); _OtherAttempts = //System.IO.TextWriter.Synchronized new ConcurrentStreamWriter(path + "OtherAttempts.txt"); //(new StreamWriter(new FileStream(path + "OtherAttempts.txt", FileMode.CreateNew, FileAccess.Write))); _logger.WriteStatus("Entered Simulator constructor"); _experimentalConfiguration = myExperimentalConfiguration; BlockingAlgorithmOptions options = _experimentalConfiguration.BlockingOptions; _logger.WriteStatus("Creating binomial ladder"); _binomialLadderFilter = new BinomialLadderFilter(options.NumberOfBitsInBinomialLadderFilter_N, options.HeightOfBinomialLadder_H); _ipHistoryCache = new ConcurrentDictionary <IPAddress, SimIpHistory>(); // new SelfLoadingCache<IPAddress, SimIpHistory>(address => new SimIpHistory(options.NumberOfFailuresToTrackForGoingBackInTimeToIdentifyTypos)); _userAccountController = new SimulatedUserAccountController(); //_memoryUsageLimiter = new MemoryUsageLimiter(); //_memoryUsageLimiter.OnReduceMemoryUsageEventHandler += ReduceMemoryUsage; _recentIncorrectPasswords = new AgingMembershipSketch(16, 128 * 1024); _logger.WriteStatus("Exiting Simulator constructor"); }
public Simulator(ExperimentalConfiguration myExperimentalConfiguration, BlockingAlgorithmOptions options = default(BlockingAlgorithmOptions)) { MyExperimentalConfiguration = myExperimentalConfiguration; if (options == null) options = new BlockingAlgorithmOptions(); CreditLimits = new[] { // 3 per hour new LimitPerTimePeriod(new TimeSpan(1, 0, 0), 3f), // 6 per day (24 hours, not calendar day) new LimitPerTimePeriod(new TimeSpan(1, 0, 0, 0), 6f), // 10 per week new LimitPerTimePeriod(new TimeSpan(6, 0, 0, 0), 10f), // 15 per month new LimitPerTimePeriod(new TimeSpan(30, 0, 0, 0), 15f) }; //We are testing with local server now MyResponsibleHosts = new MaxWeightHashing<RemoteHost>("FIXME-uniquekeyfromconfig"); //configuration.MyResponsibleHosts.Add("localhost", new RemoteHost { Uri = new Uri("http://localhost:80"), IsLocalHost = true }); RemoteHost localHost = new RemoteHost { Uri = new Uri("http://localhost:80") }; MyResponsibleHosts.Add("localhost", localHost); MyUserAccountClient = new UserAccountClient(MyResponsibleHosts, localHost); MyLoginAttemptClient = new LoginAttemptClient(MyResponsibleHosts, localHost); MemoryUsageLimiter memoryUsageLimiter = new MemoryUsageLimiter(); MyUserAccountController = new UserAccountController(MyUserAccountClient, MyLoginAttemptClient, memoryUsageLimiter, options, StableStore, CreditLimits); MyLoginAttemptController = new LoginAttemptController(MyLoginAttemptClient, MyUserAccountClient, memoryUsageLimiter, options, StableStore); MyUserAccountController.SetLoginAttemptClient(MyLoginAttemptClient); MyUserAccountClient.SetLocalUserAccountController(MyUserAccountController); MyLoginAttemptController.SetUserAccountClient(MyUserAccountClient); MyLoginAttemptClient.SetLocalLoginAttemptController(MyLoginAttemptController); //fix outofmemory bug by setting the loginattempt field to null StableStore.LoginAttempts = null; }
public SimulatedPasswords(DebugLogger logger, ExperimentalConfiguration config) { _logger = logger; _logger.WriteStatus("Loading popular password file"); LoadPasswordSelector(config.PasswordFrequencyFile); if (config.PopularPasswordsToRemoveFromDistribution > 0) { _passwordSelector = _passwordSelector.TrimToRemoveInitialItems(config.PopularPasswordsToRemoveFromDistribution); } _logger.WriteStatus("Loading passwords known to be common by the algorithm before the attack"); LoadKnownPopularPasswords(config.PreviouslyKnownPopularPasswordFile); _logger.WriteStatus("Creating common password selector"); _commonPasswordSelector = _passwordSelector.TrimToInitialItems( (int)config.NumberOfPopularPasswordsForAttackerToExploit); _logger.WriteStatus("Finished creating common password selector"); _logger.WriteStatus("Creating list of most common passwords"); OrderedListOfMostCommonPasswords = _passwordSelector.GetItems(); _logger.WriteStatus("Finished creating list of most common passwords"); }
public static void RunExperimentalSweep(ExperimentalConfiguration[] configurations) { foreach (ExperimentalConfiguration config in configurations) { DateTime now = DateTime.Now; string dirName = config.OutputPath + config.OutputDirectoryName; Directory.CreateDirectory(dirName); string path = dirName + @"\"; // Now that all of the parameters of the sweep have been set, run the simulation //TextWriter dataWriter = System.IO.TextWriter.Synchronized(new StreamWriter(path + "data.txt")); TextWriter errorWriter = //TextWriter.Synchronized (new StreamWriter(new FileStream(path + "error.txt", FileMode.CreateNew, FileAccess.Write))); DebugLogger logger = new DebugLogger(errorWriter); try { SimulatedPasswords simPasswords = new SimulatedPasswords(logger, config); Simulator simulator = new Simulator(logger, path, config, simPasswords); simulator.Run(); } catch (Exception e) { lock (errorWriter) { while (e != null) { errorWriter.WriteLine(e.Message); errorWriter.WriteLine(e.StackTrace); errorWriter.WriteLine(e); e = e.InnerException; } errorWriter.Flush(); } } } }
public IpPool(ExperimentalConfiguration experimentalConfiguration) { _experimentalConfiguration = experimentalConfiguration; }
public async Task Main(string[] args) { //for (int i = 1; i < 10; i++) //{ // ExperimentalConfiguration expConfig1 = new ExperimentalConfiguration(); // BlockingAlgorithmOptions blockConfig1 = new BlockingAlgorithmOptions(); // blockConfig1.FOR_SIMULATION_ONLY_TURN_ON_SSH_STUPID_MODE = true; // //blockConfig1.BlockThresholdUnpopularPassword = 1 * i; // //blockConfig1.BlockThresholdPopularPassword = blockConfig1.BlockThresholdUnpopularPassword; // // // // Industrial-best-practice baseline // // // // Use the same threshold regardless of the popularity of the account password // blockConfig1.BlockThresholdPopularPassword = // blockConfig1.BlockThresholdUnpopularPassword =1*i; // // Make all failures increase the count towards the threshold by one // blockConfig1.PenaltyForInvalidAccount = // blockConfig1.PenaltyMulitiplierForTypo = // blockConfig1.BasePenaltyForInvalidPassword = // 1d; // // If the below is empty, the multiplier for any popularity level will be 1. // blockConfig1.PenaltyForReachingEachPopularityThreshold = new List<PenaltyForReachingAPopularityThreshold>(); // // Correct passwords shouldn't help // blockConfig1.RewardForCorrectPasswordPerAccount = 0; // // // expConfig1.TotalLoginAttemptsToIssue = 5000; // expConfig1.RecordUnitAttempts = 5000; // //expConfig1.ChanceOfBenignPasswordTypo = 0.2d; // Simulator simulator = new Simulator(expConfig1, blockConfig1); // Console.WriteLine("Unpopularpassword {0}", blockConfig1.BlockThresholdUnpopularPassword); // // await simulator.Run(blockConfig1); //} ulong TotalLoginAttemptsToIssue = 200000; ulong RecordUnitAttempts = 200000; uint MaliciousIP = 2000; //1. Vary BlockThresholdUnpopularPassword from 100 to 2100 (in steps of 200) for (int i = 0; i < 11; i++) { ExperimentalConfiguration expConfig1 = new ExperimentalConfiguration(); BlockingAlgorithmOptions blockConfig1 = new BlockingAlgorithmOptions(); //blockConfig1.RewardForCorrectPasswordPerAccount = -10 * i - 10; //blockConfig1.PenaltyForInvalidAccount = 1 + (int)(i/3); //blockConfig1.BlockThresholdPopularPassword = 20 + 10 * i; //blockConfig1.BlockThresholdUnpopularPassword = 4*blockConfig1.BlockThresholdPopularPassword; blockConfig1.BlockThresholdUnpopularPassword = 100 + 200 * i; expConfig1.TotalLoginAttemptsToIssue = TotalLoginAttemptsToIssue; expConfig1.RecordUnitAttempts = RecordUnitAttempts; expConfig1.NumberOfIpAddressesControlledByAttacker = MaliciousIP; //blockConfig1.BlockThresholdPopularPassword = 60; //blockConfig1.BlockThresholdUnpopularPassword = 900; //blockConfig1.PenaltyForInvalidAccount = 35; //blockConfig1.PenaltyForReachingEachPopularityThreshold = new List<PenaltyForReachingAPopularityThreshold> //{ // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100*1000d), Penalty = 10*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(10*1000d), Penalty = 20*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(1*1000d), Penalty = 25*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100d), Penalty = 30*Math.Pow(2,0.3*i)}, //}; Simulator simulator = new Simulator(expConfig1, blockConfig1); Console.WriteLine("unpopularpassword {0}", blockConfig1.BlockThresholdUnpopularPassword); await simulator.Run(blockConfig1, "BlockThresholdUnpopularPassword"); } //2. Vary blockthresholdpopularpassword from 20 - 120 and unpopularpassword is 4 times for (int i = 0; i < 10; i++) { ExperimentalConfiguration expConfig1 = new ExperimentalConfiguration(); BlockingAlgorithmOptions blockConfig1 = new BlockingAlgorithmOptions(); //blockConfig1.RewardForCorrectPasswordPerAccount = -10 * i - 10; //blockConfig1.PenaltyForInvalidAccount = 1 + (int)(i/3); blockConfig1.BlockThresholdPopularPassword = 20 + 10 * i; blockConfig1.BlockThresholdUnpopularPassword = 4 * blockConfig1.BlockThresholdPopularPassword; //blockConfig1.BlockThresholdUnpopularPassword = 100 + 200 * i; expConfig1.TotalLoginAttemptsToIssue = TotalLoginAttemptsToIssue; expConfig1.RecordUnitAttempts = RecordUnitAttempts; expConfig1.NumberOfIpAddressesControlledByAttacker = 100; //blockConfig1.BlockThresholdPopularPassword = 60; //blockConfig1.BlockThresholdUnpopularPassword = 900; //blockConfig1.PenaltyForInvalidAccount = 35; //blockConfig1.PenaltyForReachingEachPopularityThreshold = new List<PenaltyForReachingAPopularityThreshold> //{ // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100*1000d), Penalty = 10*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(10*1000d), Penalty = 20*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(1*1000d), Penalty = 25*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100d), Penalty = 30*Math.Pow(2,0.3*i)}, //}; Simulator simulator = new Simulator(expConfig1, blockConfig1); Console.WriteLine("Popularpassword {0}", blockConfig1.BlockThresholdPopularPassword); await simulator.Run(blockConfig1, "BlockThresholdPopularPassword"); } //3.Vary PenaltyForInvalidAccount from 1 to 10 (in steps of 1) for (int i = 0; i < 10; i++) { ExperimentalConfiguration expConfig1 = new ExperimentalConfiguration(); BlockingAlgorithmOptions blockConfig1 = new BlockingAlgorithmOptions(); //blockConfig1.RewardForCorrectPasswordPerAccount = -10 * i - 10; blockConfig1.PenaltyForInvalidAccount = 1 + i; //blockConfig1.BlockThresholdPopularPassword = 20 + 10 * i; //blockConfig1.BlockThresholdUnpopularPassword = 4 * blockConfig1.BlockThresholdPopularPassword; //blockConfig1.BlockThresholdUnpopularPassword = 100 + 200 * i; expConfig1.TotalLoginAttemptsToIssue = TotalLoginAttemptsToIssue; expConfig1.RecordUnitAttempts = RecordUnitAttempts; expConfig1.NumberOfIpAddressesControlledByAttacker = MaliciousIP; //blockConfig1.BlockThresholdPopularPassword = 60; //blockConfig1.BlockThresholdUnpopularPassword = 900; //blockConfig1.PenaltyForInvalidAccount = 35; //blockConfig1.PenaltyForReachingEachPopularityThreshold = new List<PenaltyForReachingAPopularityThreshold> //{ // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100*1000d), Penalty = 10*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(10*1000d), Penalty = 20*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(1*1000d), Penalty = 25*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100d), Penalty = 30*Math.Pow(2,0.3*i)}, //}; Simulator simulator = new Simulator(expConfig1, blockConfig1); Console.WriteLine("PenaltyForInvalidAccount {0}", blockConfig1.PenaltyForInvalidAccount); await simulator.Run(blockConfig1, "PenaltyForInvalidAccount"); } //4.Vary RewardForCorrectPasswordPerAccount from -10 to -100 for (int i = 0; i < 10; i++) { ExperimentalConfiguration expConfig1 = new ExperimentalConfiguration(); BlockingAlgorithmOptions blockConfig1 = new BlockingAlgorithmOptions(); blockConfig1.RewardForCorrectPasswordPerAccount = -10 * i - 10; //blockConfig1.PenaltyForInvalidAccount = 1 + (int)(i/3); // blockConfig1.BlockThresholdPopularPassword = 20 + 10 * i; //blockConfig1.BlockThresholdUnpopularPassword = 4 * blockConfig1.BlockThresholdPopularPassword; //blockConfig1.BlockThresholdUnpopularPassword = 100 + 200 * i; expConfig1.TotalLoginAttemptsToIssue = TotalLoginAttemptsToIssue; expConfig1.RecordUnitAttempts = RecordUnitAttempts; expConfig1.NumberOfIpAddressesControlledByAttacker = MaliciousIP; //blockConfig1.BlockThresholdPopularPassword = 60; //blockConfig1.BlockThresholdUnpopularPassword = 900; //blockConfig1.PenaltyForInvalidAccount = 35; //blockConfig1.PenaltyForReachingEachPopularityThreshold = new List<PenaltyForReachingAPopularityThreshold> //{ // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100*1000d), Penalty = 10*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(10*1000d), Penalty = 20*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(1*1000d), Penalty = 25*Math.Pow(2,0.3*i)}, // new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100d), Penalty = 30*Math.Pow(2,0.3*i)}, //}; Simulator simulator = new Simulator(expConfig1, blockConfig1); Console.WriteLine("RewardForCorrectPasswordPerAccount {0}", blockConfig1.RewardForCorrectPasswordPerAccount); await simulator.Run(blockConfig1, "RewardForCorrectPasswordPerAccount"); } //5.PenaltyForReachingEachPopularityThreshold multiply each by 2 ^{ 0.3 * k} k0-10 for (int i = 0; i < 11; i++) { ExperimentalConfiguration expConfig1 = new ExperimentalConfiguration(); BlockingAlgorithmOptions blockConfig1 = new BlockingAlgorithmOptions(); //blockConfig1.RewardForCorrectPasswordPerAccount = -10 * i - 10; //blockConfig1.PenaltyForInvalidAccount = 1 + (int)(i/3); // blockConfig1.BlockThresholdPopularPassword = 20 + 10 * i; //blockConfig1.BlockThresholdUnpopularPassword = 4 * blockConfig1.BlockThresholdPopularPassword; //blockConfig1.BlockThresholdUnpopularPassword = 100 + 200 * i; expConfig1.TotalLoginAttemptsToIssue = TotalLoginAttemptsToIssue; expConfig1.RecordUnitAttempts = RecordUnitAttempts; expConfig1.NumberOfIpAddressesControlledByAttacker = MaliciousIP; //blockConfig1.BlockThresholdPopularPassword = 60; //blockConfig1.BlockThresholdUnpopularPassword = 900; //blockConfig1.PenaltyForInvalidAccount = 35; blockConfig1.PenaltyForReachingEachPopularityThreshold = new List<PenaltyForReachingAPopularityThreshold> { new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100*1000d), Penalty = 10*Math.Pow(2,0.3*i)}, new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(10*1000d), Penalty = 20*Math.Pow(2,0.3*i)}, new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(1*1000d), Penalty = 25*Math.Pow(2,0.3*i)}, new PenaltyForReachingAPopularityThreshold { PopularityThreshold = 1d/(100d), Penalty = 30*Math.Pow(2,0.3*i)}, }; Simulator simulator = new Simulator(expConfig1, blockConfig1); Console.WriteLine("PenaltyForReachingEachPopularityThreshold{0}", blockConfig1.PenaltyForReachingEachPopularityThreshold); await simulator.Run(blockConfig1, "PenaltyForReachingEachPopularityThreshold"); } //ExperimentalConfiguration expConfig = new ExperimentalConfiguration(); //BlockingAlgorithmOptions blockConfig = new BlockingAlgorithmOptions(); //Simulator simulator = new Simulator(expConfig, blockConfig); //await simulator.Run(); }
public void SetParameter(ExperimentalConfiguration config, int parameterIndex) { ParameterSetter(config, Parameters[parameterIndex]); }
/// <summary> /// Create accounts, generating passwords, primary IP /// </summary> public void Generate(ExperimentalConfiguration experimentalConfiguration) { SimulatedUserAccountController simUserAccountController = new SimulatedUserAccountController(); _logger.WriteStatus("Creating {0:N0} benign accounts", experimentalConfiguration.NumberOfBenignAccounts); 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 = 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); // // 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 = simUserAccountController.Create( "attacker_" + index.ToString(), _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) simUserAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBefore( simAccount, LoginAttempt.HashCookie(cookie)); }); _logger.WriteStatus("Finished creating user accounts for each simluated account record"); }
public static async Task RunExperimentalSweep( ExperimentalConfigurationFunction configurationDelegate, IParameterSweeper[] parameterSweeps = null, int startingTest = 0) { int totalTests = parameterSweeps == null ? 1 : // Get the legnths of each dimension of the multi-dimensional parameter sweep parameterSweeps.Select(ps => ps.GetParameterCount()) // Calculates the product of the number of parameters in each dimension .Aggregate((runningProduct, nextFactor) => runningProduct * nextFactor); ExperimentalConfiguration baseConfig = new ExperimentalConfiguration(); configurationDelegate(baseConfig); DateTime now = DateTime.Now; string dirName = baseConfig.OutputPath + baseConfig.OutputDirectoryName + "_Run_" + now.Month + "_" + now.Day + "_" + now.Hour + "_" + now.Minute; if (parameterSweeps != null) { Directory.CreateDirectory(dirName); } for (int testIndex = startingTest; testIndex < totalTests; testIndex++) { // Start with the default configuration from the provided configuration factory ExperimentalConfiguration config = new ExperimentalConfiguration(); configurationDelegate(config); // Next set the parameters for this test in the swwep string path = dirName + (parameterSweeps == null ? "" : ("\\Expermient" + testIndex.ToString())); Directory.CreateDirectory(path); path += @"\"; int parameterIndexer = testIndex; if (parameterSweeps != null) { for (int dimension = parameterSweeps.Length - 1; dimension >= 0; dimension--) { IParameterSweeper sweep = parameterSweeps[dimension]; int parameterIndex = parameterIndexer % sweep.GetParameterCount(); parameterIndexer /= sweep.GetParameterCount(); sweep.SetParameter(config, parameterIndex); path += "_" + sweep.GetParameterString(parameterIndex).Replace(".", "_"); } } // Now that all of the parameters of the sweep have been set, run the simulation //TextWriter dataWriter = System.IO.TextWriter.Synchronized(new StreamWriter(path + "data.txt")); TextWriter errorWriter = //TextWriter.Synchronized (new StreamWriter(new FileStream(path + "error.txt", FileMode.CreateNew, FileAccess.Write))); DebugLogger logger = new DebugLogger(errorWriter); try { SimulatedPasswords simPasswords = new SimulatedPasswords(logger, config); Simulator simulator = new Simulator(logger, path, config, simPasswords); await simulator.Run(); } catch (Exception e) { while (e != null) { errorWriter.WriteLine(e.Message); errorWriter.WriteLine(e.StackTrace); errorWriter.WriteLine(e); e = e.InnerException; } errorWriter.Flush(); } } }
/// <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"); }
public static ExperimentalConfiguration GetConfig( ExperimentalConfiguration.AttackStrategy attack = ExperimentalConfiguration.AttackStrategy.BreadthFirst, int pwToBan = 100, double fractionOfBenignIPsBehindProxies = 0.1, double fractionOfMaliciousIPsToOverlapWithBenign = .01d, double fractionOfLoginAttemptsFromAttacker = 0.5d, double extraTypoFactor = 1d, ulong scale = 1, string addToName = null) { ExperimentalConfiguration config = new ExperimentalConfiguration(); // Scale of test config.AttackersStrategy = attack; config.PopularPasswordsToRemoveFromDistribution = pwToBan; config.FractionOfBenignIPsBehindProxies = fractionOfBenignIPsBehindProxies; config.FractionOfMaliciousIPsToOverlapWithBenign = fractionOfMaliciousIPsToOverlapWithBenign; ulong totalLoginAttempts = scale * Million; config.TestTimeSpan = new TimeSpan(7, 0, 0, 0); // 7 days double meanNumberOfLoginsPerBenignAccountDuringExperiment = 100d; double meanNumberOfLoginsPerAttackerControlledIP = 1000d; DateTime now = DateTime.Now; string dirName = BasePath + "Run_" + totalLoginAttempts + "_" + now.Month + "_" + now.Day + "_" + now.Hour + "_" + now.Minute; Directory.CreateDirectory(dirName); config.OutputPath = dirName + @"\"; config.OutputDirectoryName = string.Format("{0}_Strategy_{1}_Remove_{2}_Proxies_{3}_Overlap_{4}", addToName == null ? "" : addToName + "_", //(int)Math.Log10(totalLoginAttempts), config.AttackersStrategy == ExperimentalConfiguration.AttackStrategy.BreadthFirst ? "BreadthFirst" : config.AttackersStrategy == ExperimentalConfiguration.AttackStrategy.Weighted ? "Weighted" : "Avoid", config.PopularPasswordsToRemoveFromDistribution, (int)1000 * config.FractionOfBenignIPsBehindProxies, (int)1000 * config.FractionOfMaliciousIPsToOverlapWithBenign ); // Figure out parameters from scale double fractionOfLoginAttemptsFromBenign = 1d - fractionOfLoginAttemptsFromAttacker; double expectedNumberOfBenignAttempts = totalLoginAttempts * fractionOfLoginAttemptsFromBenign; double numberOfBenignAccounts = expectedNumberOfBenignAttempts / meanNumberOfLoginsPerBenignAccountDuringExperiment; double expectedNumberOfAttackAttempts = totalLoginAttempts * fractionOfLoginAttemptsFromAttacker; double numberOfAttackerIps = expectedNumberOfAttackAttempts / meanNumberOfLoginsPerAttackerControlledIP; // Make any changes to the config or the config.BlockingOptions within config here config.TotalLoginAttemptsToIssue = totalLoginAttempts; config.FractionOfLoginAttemptsFromAttacker = fractionOfLoginAttemptsFromAttacker; config.NumberOfBenignAccounts = (uint)numberOfBenignAccounts; // Scale of attackers resources config.NumberOfIpAddressesControlledByAttacker = (uint)numberOfAttackerIps; config.NumberOfAttackerControlledAccounts = (uint)numberOfAttackerIps; // Additional sources of false positives/negatives config.ProxySizeInUniqueClientIPs = 1000; // Make typos almost entirely ignored config.ChanceOfBenignPasswordTypo *= extraTypoFactor; // Blocking parameters config.BlockingOptions.HeightOfBinomialLadder_H = 48; config.BlockingOptions.NumberOfBitsInBinomialLadderFilter_N = 1 << 29; config.BlockingOptions.BinomialLadderFrequencyThreshdold_T = 44; config.BlockingOptions.ExpensiveHashingFunctionIterations = 1; return(config); }
/// <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"); }
//public void ReduceMemoryUsage(object sender, MemoryUsageLimiter.ReduceMemoryUsageEventParameters parameters) //{ //_ipHistoryCache.RecoverSpace(parameters.FractionOfMemoryToTryToRemove); //} public Simulator(DebugLogger logger, string path, ExperimentalConfiguration myExperimentalConfiguration, SimulatedPasswords simPasswords) { _simPasswords = simPasswords; _logger = logger; _AttackAttemptsWithValidPasswords = //System.IO.TextWriter.Synchronized new ConcurrentStreamWriter(path + "AttackAttemptsWithValidPasswords.txt"); //(new StreamWriter(new FileStream(path + "AttackAttemptsWithValidPasswords.txt", FileMode.CreateNew, FileAccess.Write))); _LegitimateAttemptsWithValidPasswords = //System.IO.TextWriter.Synchronized new ConcurrentStreamWriter(path + "LegitimateAttemptsWithValidPasswords.txt"); //(new StreamWriter(new FileStream(path + "LegitiamteAttemptsWithValidPasswords.txt", FileMode.CreateNew, FileAccess.Write))); _OtherAttempts = //System.IO.TextWriter.Synchronized new ConcurrentStreamWriter(path + "OtherAttempts.txt"); //(new StreamWriter(new FileStream(path + "OtherAttempts.txt", FileMode.CreateNew, FileAccess.Write))); _logger.WriteStatus("Entered Simulator constructor"); _experimentalConfiguration = myExperimentalConfiguration; BlockingAlgorithmOptions options = _experimentalConfiguration.BlockingOptions; _logger.WriteStatus("Creating binomial ladder"); _binomialLadderFilter = new BinomialLadderFilter(options.NumberOfBitsInBinomialLadderFilter_N, options.HeightOfBinomialLadder_H); _ipHistoryCache = new ConcurrentDictionary<IPAddress, SimIpHistory>(); // new SelfLoadingCache<IPAddress, SimIpHistory>(address => new SimIpHistory(options.NumberOfFailuresToTrackForGoingBackInTimeToIdentifyTypos)); _userAccountController = new SimulatedUserAccountController(); //_memoryUsageLimiter = new MemoryUsageLimiter(); //_memoryUsageLimiter.OnReduceMemoryUsageEventHandler += ReduceMemoryUsage; _recentIncorrectPasswords = new AgingMembershipSketch(16, 128 * 1024); _logger.WriteStatus("Exiting Simulator constructor"); }
public static ExperimentalConfiguration GetConfig( ExperimentalConfiguration.AttackStrategy attack = ExperimentalConfiguration.AttackStrategy.BreadthFirst, int pwToBan = 100, double fractionOfBenignIPsBehindProxies = 0.1, double fractionOfMaliciousIPsToOverlapWithBenign = .1d, double fractionOfLoginAttemptsFromAttacker = 0.5d, double extraTypoFactor = 1d, ulong scale = 1, string addToName = null) { ExperimentalConfiguration config = new ExperimentalConfiguration(); // Scale of test config.AttackersStrategy = attack; config.PopularPasswordsToRemoveFromDistribution = pwToBan; config.FractionOfBenignIPsBehindProxies = fractionOfBenignIPsBehindProxies; config.FractionOfMaliciousIPsToOverlapWithBenign = fractionOfMaliciousIPsToOverlapWithBenign; ulong totalLoginAttempts = scale * Million; config.TestTimeSpan = new TimeSpan(7, 0, 0, 0); // 7 days double meanNumberOfLoginsPerBenignAccountDuringExperiment = 100d; double meanNumberOfLoginsPerAttackerControlledIP = 100d; DateTime now = DateTime.Now; string dirName = BasePath + "Run_" + totalLoginAttempts + "_" + now.Month + "_" + now.Day + "_" + now.Hour + "_" + now.Minute; Directory.CreateDirectory(dirName); config.OutputPath = dirName + @"\"; config.OutputDirectoryName = string.Format("{0}_Strategy_{1}_Remove_{2}_Proxies_{3}_Overlap_{4}", addToName == null ? "" : addToName + "_", //(int)Math.Log10(totalLoginAttempts), config.AttackersStrategy == ExperimentalConfiguration.AttackStrategy.BreadthFirst ? "BreadthFirst" : config.AttackersStrategy == ExperimentalConfiguration.AttackStrategy.Weighted ? "Weighted" : "Avoid", config.PopularPasswordsToRemoveFromDistribution, (int)1000 * config.FractionOfBenignIPsBehindProxies, (int)1000 * config.FractionOfMaliciousIPsToOverlapWithBenign ); // Figure out parameters from scale double fractionOfLoginAttemptsFromBenign = 1d - fractionOfLoginAttemptsFromAttacker; double expectedNumberOfBenignAttempts = totalLoginAttempts * fractionOfLoginAttemptsFromBenign; double numberOfBenignAccounts = expectedNumberOfBenignAttempts / meanNumberOfLoginsPerBenignAccountDuringExperiment; double expectedNumberOfAttackAttempts = totalLoginAttempts * fractionOfLoginAttemptsFromAttacker; double numberOfAttackerIps = expectedNumberOfAttackAttempts / meanNumberOfLoginsPerAttackerControlledIP; // Make any changes to the config or the config.BlockingOptions within config here config.TotalLoginAttemptsToIssue = totalLoginAttempts; config.FractionOfLoginAttemptsFromAttacker = fractionOfLoginAttemptsFromAttacker; config.NumberOfBenignAccounts = (uint)numberOfBenignAccounts; // Scale of attackers resources config.NumberOfIpAddressesControlledByAttacker = (uint)numberOfAttackerIps; config.NumberOfAttackerControlledAccounts = (uint)numberOfAttackerIps; // Additional sources of false positives/negatives config.ProxySizeInUniqueClientIPs = 1000; // Make typos almost entirely ignored config.ChanceOfBenignPasswordTypo *= extraTypoFactor; // Blocking parameters config.BlockingOptions.HeightOfBinomialLadder_H = 48; config.BlockingOptions.NumberOfBitsInBinomialLadderFilter_N = 1 << 29; config.BlockingOptions.BinomialLadderFrequencyThreshdold_T = 44; config.BlockingOptions.ExpensiveHashingFunctionIterations = 1; return config; }
/// <summary> /// Create accounts, generating passwords, primary IP /// </summary> public void Generate(ExperimentalConfiguration experimentalConfiguration) { SimulatedUserAccountController simUserAccountController = new SimulatedUserAccountController(); _logger.WriteStatus("Creating {0:N0} benign accounts", experimentalConfiguration.NumberOfBenignAccounts); 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 = 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); // // 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 = simUserAccountController.Create( "attacker_" + index.ToString(), _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) { simUserAccountController.HasClientWithThisHashedCookieSuccessfullyLoggedInBefore( simAccount, LoginAttempt.HashCookie(cookie)); } }); _logger.WriteStatus("Finished creating user accounts for each simluated account record"); }