public void ExactStringBucketer_SimpleStrings_MultipleBucket() { ExactStringBucketer bucketer = new ExactStringBucketer(); RequestSequence sequence1 = GenerateSequence(1, "non-matching 1"); RequestSequence sequence2 = GenerateSequence(1, "non-matching 2"); bucketer.Add(sequence1); bucketer.Add(sequence2); Assert.Equal(2, bucketer.Bucketize().Count); }
public void ExactStringBucketer_SimpleStrings_SingleBucket() { ExactStringBucketer bucketer = new ExactStringBucketer(); RequestSequence sequence1 = GenerateSequence(1, "matching"); RequestSequence sequence2 = GenerateSequence(1, "matching"); bucketer.Add(sequence1); bucketer.Add(sequence2); Assert.Single(bucketer.Bucketize()); }
public bool Add(RequestSequence sequence) { List <Response> responses = sequence.GetResponses(); Response response = responses[responses.Count - 1]; List <TokenCollection> allResults = sequence.GetResults(); TokenCollection results = allResults[allResults.Count - 1]; SortedSet <string> tokenNames = new SortedSet <string>(); foreach (IToken token in results) { if (UseValueOverrides.Contains(token.Name)) { tokenNames.Add($"{token.Name}:{token.Value}"); } else { tokenNames.Add(token.Name); } } StringBuilder sb = new StringBuilder(); sb.Append(response.Status.ToString()); if (response.Status != System.Net.HttpStatusCode.RequestTimeout) { foreach (string name in tokenNames) { sb.Append(name); } } if (!sequence.GetDebugMetadata().Exists(x => x.Type == "BucketDebug")) { sequence.AddMetadata("BucketDebug", sb.ToString()); } if (!Sorted.ContainsKey(sb.ToString())) { Console.WriteLine($"Added new bucket {sb.ToString()}"); Sorted.Add(sb.ToString(), new List <RequestSequence>()); Sorted[sb.ToString()].Add(sequence); return(true); } Sorted[sb.ToString()].Add(sequence); return(false); }
public IEnumerable <RequestSequence> Generate(List <KnownEndpoint> endpoints, RequestSequence sequence, List <TokenCollection> sequenceResults) { // Only build off sequences that have an actual result. if (sequence.GetLastResponse() == null || (int)sequence.GetLastResponse().Status < 300) { // Search for an endpoint that we can append to the end of this request sequence. foreach (KnownEndpoint endpoint in endpoints) { bool foundMatch = true; TokenCollection requirements = endpoint.InputTokens; Stage candidateStage = new Stage(endpoint.Request.Clone()); foreach (IToken token in requirements) { int matchIndex = 0; IToken?matchToken = null; // Substituting a token with the same name is usually a good bet, but sometimes gets stuck if there is a false positive. // Add some level of randomness to keep things working. int skip = Rand.Next(0, 2); if (skip >= 2 && GetRandomNameMatch(sequenceResults, token.Name, out matchToken, out matchIndex)) { // Find a token that has the same name as this one. candidateStage.Substitutions.Add(new SubstituteNamedToken(token, matchToken, matchIndex)); } else if (skip >= 1 && GetRandomTypeMatch(sequenceResults, token.SupportedTypes, out matchToken, out matchIndex)) { // Find a token that has the same type as this one. candidateStage.Substitutions.Add(new SubstituteNamedToken(token, matchToken, matchIndex)); } else { // Use the original value from the example request. candidateStage.Substitutions.Add(new SubstituteConstant(token, token.Value)); } } if (foundMatch) { RequestSequence newSequence = sequence.Copy(); newSequence.Add(candidateStage); yield return(newSequence); } } } }
public bool Add(RequestSequence sequence) { List <Response> responses = sequence.GetResponses(); Response response = responses[responses.Count - 1]; StringBuilder sb = new StringBuilder(); sb.Append(response.Status.ToString()); if (!Sorted.ContainsKey(sb.ToString())) { Sorted.Add(sb.ToString(), new List <RequestSequence>()); Sorted[sb.ToString()].Add(sequence); return(true); } Sorted[sb.ToString()].Add(sequence); return(false); }
RequestSequence GenerateSequence(int numStages, string responseContent) { RequestSequence sequence = new RequestSequence(); // Force creation of the results list by 'executing' the empty sequence. sequence.Execute(null, null, null); for (int i = 0; i < numStages; ++i) { Request request = new Request(new Uri(@"http://localhost/rest/user/login/"), HttpMethod.Get); request.Content = "{ \"email\":\"[email protected]\",\"password\":\"123456\"}"; sequence.Add(new Stage(request)); Response response = new Response(System.Net.HttpStatusCode.OK, responseContent); sequence.GetResponses().Add(response); } return(sequence); }
public IEnumerable <RequestSequence> Generate(List <KnownEndpoint> endpoints, RequestSequence sequence, List <TokenCollection> sequenceResults) { if (dictionary.Count == 0) { yield break; } for (int i = 0; i < MaxSubstitutions; ++i) { if (sequence.StageCount() == 0) { continue; } RequestSequence newSequence = sequence.Copy(); int selectedStage = rand.Next(0, newSequence.StageCount()); Stage stage = newSequence.Get(selectedStage); if (stage.Substitutions.Count == 0) { continue; } int subIndex = rand.Next(0, newSequence.Get(selectedStage).Substitutions.Count); ISubstitution sub = newSequence.Get(selectedStage).Substitutions[subIndex]; newSequence.Get(selectedStage).Substitutions.RemoveAt(subIndex); string replacement = dictionary[rand.Next(0, dictionary.Count)]; SubstituteConstant substituteConstant = new SubstituteConstant(sub.GetTarget(), replacement); newSequence.Get(selectedStage).Substitutions.Add(substituteConstant); yield return(newSequence); } yield break; }
public void MinimizePopulation() { Population = new List <RequestSequence>(); // We always need the option of starting from an empty sequence. Population.Add(new RequestSequence()); foreach (IBucketer bucketer in Bucketers.Values) { // Get the bucketed requests, then reset the bucketer to free up memory. List <List <RequestSequence> > buckets = bucketer.Bucketize(); bucketer.Reset(); // Go through each bucket and pick the shortest sequence to save. foreach (List <RequestSequence> bucket in buckets) { RequestSequence shortest = null; foreach (RequestSequence candidate in bucket) { bool candidateIsValid = (candidate.GetResponses().Count > 0 && candidate.GetLastResponse().Status != HttpStatusCode.RequestTimeout); if (candidateIsValid && (shortest == null || (candidate.StageCount() < shortest.StageCount() || (candidate.StageCount() == shortest.StageCount() && candidate.SubstitutionCount() < shortest.SubstitutionCount())))) { shortest = candidate; } } if (shortest != null) { Population.Add(shortest); bucketer.Add(shortest); } } } }
public void AddResponse(RequestSequence sequence) { Request finalRequest = sequence.Get(sequence.StageCount() - 1).Request; Bucketers[finalRequest.OriginalEndpoint].Add(sequence); }
public async Task AddRequestSequence(RequestSequence sequence, FuzzerRunEntity run) { RequestSequenceEntity model = new RequestSequenceEntity(); model.request_count = sequence.StageCount(); model.substitution_count = sequence.SubstitutionCount(); model.run_id = run.id.GetValueOrDefault(0); using (var connection = GetConnection()) { connection.Open(); model.id = connection.Query <int>( @"INSERT INTO sequences ( request_count, substitution_count, run_id ) VALUES ( @request_count, @substitution_count, @run_id ) RETURNING id;", model).First(); foreach (SequenceMetadata meta in sequence.GetDebugMetadata()) { SequenceMetadataEntity metadata_entity = new SequenceMetadataEntity { sequence_id = model.id, content = meta.Content, type = meta.Type }; connection.Execute(@"INSERT INTO sequence_metadata ( sequence_id, type, content ) VALUES ( @sequence_id, @type, @content );", metadata_entity); } } sequence.Id = model.id; List <Response>?results = sequence.GetResponses(); if (results != null && results.Count == sequence.StageCount()) { for (int i = 0; i < sequence.StageCount(); ++i) { Request request = sequence.Get(i).Request; RequestEntity requestModel = RequestEntity.FromRequest(request); requestModel.sequence_id = model.id; requestModel.sequence_position = i; AddExecutedRequest(requestModel); request.Id = requestModel.id; Response response = results[i]; ResponseEntity responseModel = ResponseEntity.FromResponse(response); responseModel.sequence_id = model.id; responseModel.sequence_position = i; AddResponse(responseModel); response.Id = responseModel.id; foreach (ISubstitution sub in sequence.Get(i).Substitutions) { SubstitutionEntity subModel = SubstitutionEntity.FromSubstitution(sub); subModel.sequence_id = model.id; subModel.sequence_position = i; AddSubstitution(subModel); } } if (sequence.GetLastResponse() != null) { int statusCode = (int)sequence.GetLastResponse().Status; RequestSequenceLabelEntity labelEntity = new RequestSequenceLabelEntity(); labelEntity.sequence_id = model.id.Value; if (statusCode >= 100 && statusCode < 200) { labelEntity.name = "Informational"; } else if (statusCode >= 200 && statusCode < 300) { labelEntity.name = "Success"; } else if (statusCode >= 300 && statusCode < 400) { labelEntity.name = "Redirection"; } else if (statusCode >= 400 && statusCode < 500) { labelEntity.name = "Client Error"; } else if (statusCode >= 500 && statusCode < 600) { labelEntity.name = "Server Error"; } else { labelEntity.name = "Unknown Status"; } await AddRequestSequenceLabel(labelEntity); } } else { Console.WriteLine("Warning: Truncated request sequence."); } }