/// <summary> /// Gets executed async /// </summary> private void TestThread() { while (IsRunning) { TestJob testJob = null; int testJobHash = -1; lock (_lock) { if (_testsQueue.Count > 0) { testJob = _testsQueue.Dequeue(); testJobHash = testJob.GetHashCode(); _inProgressList.Add(testJobHash); } } if (testJob != null) { _tester.ExecuteTests(_rawRequest, _rawResponse, _reqUri, testJob.ParameterName, testJob.ParameterValue, testJob.RequestLocation, testJob.TestDef); } lock (_lock) { _inProgressList.Remove(testJobHash); } } }
protected string GetUpdatedParameterValue(HttpRequestInfo curWorkingReqInfo, TestJob testJob) { string val = null; HttpVariables variables = null; HTTPHeaders headers = null; switch (testJob.RequestLocation) { case RequestLocation.Body: variables = curWorkingReqInfo.BodyVariables; break; case RequestLocation.Path: variables = curWorkingReqInfo.PathVariables; break; case RequestLocation.Query: variables = curWorkingReqInfo.QueryVariables; break; case RequestLocation.Cookies: variables = curWorkingReqInfo.Cookies; break; case RequestLocation.Headers: headers = curWorkingReqInfo.Headers; break; } if (variables != null && variables.ContainsKey(testJob.ParameterName)) { val = variables[testJob.ParameterName]; } else if (headers != null) { val = headers[testJob.ParameterName]; } return(val); }
/// <summary> /// Get a payload list for the mutation /// </summary> /// <param name="rawRequest"></param> /// <param name="mutationRule"></param> /// <param name="hasFuzz">Whether the request contains <fuzz></param> /// <param name="entityId">The entitiy id</param> /// <returns></returns> public List <string> GeneratePayloadListFromMutation(string rawRequest, TestJob testJob, bool hasFuzz, string entityId) { List <string> payloadList = new List <string>(); string mutationRule = testJob.TestDef.Mutation; string payloadString = ""; if (mutationRule.StartsWith(JAVASCRIPT_FUNCTION_TAG)) { //extract JS function from rule string jsCode = mutationRule.Substring(JAVASCRIPT_FUNCTION_TAG.Length); //function should match the signature Callback(<string>,<string>, using (ScriptEngine engine = new ScriptEngine(ScriptEngine.JavaScriptLanguage)) { ParsedScript parsed = engine.Parse(jsCode); payloadString = parsed.CallMethod(CALLBACK_NAME, rawRequest, testJob.ParameterName, testJob.ParameterValue, testJob.RequestLocation.ToString()) as string; } } else { payloadString = mutationRule; } if (hasFuzz) { payloadString = payloadString.Replace("$original", String.Empty); } else { payloadString = payloadString.Replace("$original", testJob.ParameterValue); } payloadString = payloadString.Replace("$entity_id", entityId); if (!String.IsNullOrWhiteSpace(payloadString)) { payloadString = payloadString.Replace(@"\,", "__comma__"); var list = payloadString.Split(','); foreach (string payload in list) { string finalPayload = payload.Replace("__comma__", ","); payloadList.Add(finalPayload); if (_testFile.GenerateAllEncodings) //also add encoding variants for the payload { payloadList.Add(Utils.UrlEncode(finalPayload)); payloadList.Add(Utils.UrlEncode(Utils.UrlEncode(finalPayload))); payloadList.Add(Utils.UrlEncodeAll(finalPayload)); payloadList.Add(Utils.JSONEncode(finalPayload)); payloadList.Add(Utils.HtmlEncode(finalPayload)); payloadList.Add(Utils.Base64Encode(finalPayload)); } } } return(payloadList); }
/// <summary> /// Mutates a request in order to execute a test /// </summary> /// <param name="rawRequest"></param> /// <param name="parameterName"></param> /// <param name="parameterValue"></param> /// <param name="reqLocation"></param> /// <param name="entityString"></param> /// <param name="entityId"></param> /// <param name="testDef"></param> /// <returns></returns> public List <string> GenerateMutatedRequestList(string rawRequest, TestJob testJob, string entityString, string entityId) { //generate payload bool hasFuzz = rawRequest.Contains(Constants.FUZZ_STRING) || rawRequest.Contains(ENCODED_FUZZ); List <string> mutatedRequestsList = new List <string>(); List <string> payloadList = GeneratePayloadListFromMutation(rawRequest, testJob, hasFuzz, entityId); for (int i = 0; i < payloadList.Count; i++) { string payload = payloadList[i]; _testController.Log("Running test '{0}' with payload: '{1}'", testJob.TestDef.Name, payload); string mutatedRequest; if (hasFuzz) { mutatedRequest = rawRequest.Replace(Constants.FUZZ_STRING, payload); mutatedRequest = mutatedRequest.Replace(ENCODED_FUZZ, payload); } else if (entityString != null && OccurenceCount(entityString, testJob.ParameterValue) == 1) { string mutatedString = entityString.Replace(testJob.ParameterValue, payload); mutatedRequest = rawRequest.Replace(entityString, mutatedString); } else { //try to parse the request HttpRequestInfo mutatedReqInfo = new HttpRequestInfo(rawRequest, true); //attempt to find the parameter switch (testJob.RequestLocation) { case RequestLocation.Body: mutatedReqInfo.BodyVariables.Set(testJob.ParameterName, payload); break; case RequestLocation.Cookies: mutatedReqInfo.Cookies.Set(testJob.ParameterName, payload); break; case RequestLocation.Headers: mutatedReqInfo.Headers[testJob.ParameterName] = payload; break; case RequestLocation.Query: mutatedReqInfo.QueryVariables.Set(testJob.ParameterName, payload); break; case RequestLocation.Path: mutatedReqInfo.PathVariables.Set(testJob.ParameterName, payload); break; } mutatedRequest = mutatedReqInfo.ToString(); } //update dynamic values mutatedRequest = mutatedRequest.Replace("__dynamic_value__ticks__", (DateTime.Now.Ticks + i).ToString()); mutatedRequestsList.Add(mutatedRequest); } return(mutatedRequestsList); }
/// <summary> /// Gets executed async /// </summary> private void TestThread() { while (_runnable) { TestJob testJob = null; lock (_lock) { if (_testsQueue.Count > 0) { testJob = _testsQueue.Dequeue(); } else { _runnable = false; } } if (testJob != null) { _tester.ExecuteTests(_rawRequest, _rawResponse, _reqUri, testJob.ParameterName, testJob.ParameterValue, testJob.RequestLocation, testJob.TestDef); } } }
/// <summary> /// Handles a request /// </summary> /// <param name="requestInfo"></param> /// <returns></returns> public HttpRequestInfo HandleRequest(HttpRequestInfo requestInfo, out bool mutated) { lock (_lock) { mutated = false; //make a request info that we parse in order to generate a hash and entities to test _curWorkingRawRequest = requestInfo.ToString(); if (!ShouldBeTested(_curWorkingRawRequest)) { return(requestInfo); } _curWorkingReqInfo = new HttpRequestInfo(_curWorkingRawRequest, true); _curWorkingReqInfo.IsSecure = requestInfo.IsSecure; int hash = _curWorkingReqInfo.GetHashCode(TrafficServerMode.IgnoreCookies); //get a hash including only the parameter names if (_firstRequestHash == 0) { _firstRequestHash = hash; } if (hash == _firstRequestHash) { if (_currentReqIdx > _detectedFlowRequests) { _detectedFlowRequests = _currentReqIdx + 1; } //reset the counter _currentReqIdx = 0; } else { //increment the request counter _currentReqIdx++; } if (_currentTestReqIdx < 0) //this is the first request { if (String.IsNullOrEmpty(_testFile.PatternOfFirstRequestToTest)) //if this is not the first request { _currentTestReqIdx = 0; } else { if (Utils.IsMatch(_curWorkingRawRequest, _testFile.PatternOfFirstRequestToTest)) { _currentTestReqIdx = _currentReqIdx; } } } if (_currentReqIdx == _currentTestReqIdx) { if (!_workList.ContainsKey(_currentTestReqIdx)) //no tests have been generated for this request { GenerateEntities(_currentReqIdx, _curWorkingReqInfo); } //this is the test request execute the next test Queue <TestJob> testQueue = _workList[_currentTestReqIdx]; if (testQueue.Count == 0 && _curMutatedRawReqQueue.Count == 0) { _currentTestReqIdx++; } else { if (_curMutatedRawReqQueue.Count == 0) { _curTestJob = testQueue.Dequeue(); //TODO: alter the request Uri workingReqUri = new Uri(_curWorkingReqInfo.FullUrl); _curEntityId = _tester.GetEntityId(workingReqUri, _curTestJob.ParameterName); string entityString = _tester.GetEntityString(_curWorkingRawRequest, workingReqUri, _curTestJob.ParameterName, _curTestJob.ParameterValue); if (entityString == null)//we could not find the parameter name /value combination { //try to obtain an updated value for the parameter string updatedParameterValue = GetUpdatedParameterValue(_curWorkingReqInfo, _curTestJob); entityString = _tester.GetEntityString(_curWorkingRawRequest, workingReqUri, _curTestJob.ParameterName, updatedParameterValue); } _curMutatedRequestList = _tester.GenerateMutatedRequestList(_curWorkingRawRequest, _curTestJob, entityString, _curEntityId); foreach (string req in _curMutatedRequestList) { _curMutatedRawReqQueue.Enqueue(req); } _curTestResponseCollection = new Dictionary <int, List <string> >(); //re-init the current test response list for multi response validation } //check again in case for some reason requests could not be generated (empty parameters) if (_curMutatedRawReqQueue.Count > 0) { //if multiple mutations are generated for the test then they need to be executed with each flow iteration _curMutatedRawReq = _curMutatedRawReqQueue.Dequeue(); //return the mutated request requestInfo = new HttpRequestInfo(_curMutatedRawReq, false); requestInfo.IsSecure = _curWorkingReqInfo.IsSecure; mutated = true; } } } } return(requestInfo); }
protected void GenerateEntities(int requestId, HttpRequestInfo workingReqInfo) { Queue <TestJob> workQueue = new Queue <TestJob>(); var customTests = _testFile.GetCustomTests().Values; string entityExclusion = _testFile.PatternEntityExclusion; foreach (var test in customTests) { //iterate through parameters, cookies and headers foreach (var pathParameter in workingReqInfo.PathVariables) { if (!Utils.IsMatch(pathParameter.Key, entityExclusion)) { TestJob testJob = new TestJob(pathParameter.Key, pathParameter.Value, RequestLocation.Path, test); workQueue.Enqueue(testJob); } } foreach (var queryParameter in workingReqInfo.QueryVariables) { if (!Utils.IsMatch(queryParameter.Key, entityExclusion)) { TestJob testJob = new TestJob(queryParameter.Key, queryParameter.Value, RequestLocation.Query, test); workQueue.Enqueue(testJob); } } foreach (var bodyParameter in workingReqInfo.BodyVariables) { if (!Utils.IsMatch(bodyParameter.Key, entityExclusion)) { TestJob testJob = new TestJob(bodyParameter.Key, bodyParameter.Value, RequestLocation.Body, test); workQueue.Enqueue(testJob); } } if (!_testFile.TestOnlyParameters) { foreach (var header in workingReqInfo.Headers) { if (!Utils.IsMatch(header.Name, entityExclusion)) { if (!header.Name.Equals("Host")) { TestJob testJob = new TestJob(header.Name, header.Value, RequestLocation.Headers, test); workQueue.Enqueue(testJob); } } } foreach (var cookie in workingReqInfo.Cookies) { if (!Utils.IsMatch(cookie.Key, entityExclusion)) { TestJob testJob = new TestJob(cookie.Key, cookie.Value, RequestLocation.Cookies, test); workQueue.Enqueue(testJob); } } } } _workList.Add(requestId, workQueue); }