/// <summary> /// Browser waits for XML document implementation. /// </summary> /// <param name="browserType"> /// Browser type. /// </param> private void BrowserWaitsForXmlDocumentImplementation(BrowserType browserType) { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { browserType, 1 } }; const int MaxWait = 10; using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(browserType); var stopWatch = new Stopwatch(); stopWatch.Start(); // make the request, wait for up to 10 seconds. browser.NavigateTo($"{Constants.VulnerabilitiesAddress}XmlResponse.aspx"); browser.WaitForPageLoad(MaxWait); stopWatch.Stop(); // FF and Chrome will return the XML content, IE returns the XML with styles applied. browser.PageSource.ShouldContain("content"); stopWatch.ElapsedMilliseconds.ShouldBeLessThan((MaxWait + 1) * 1000); } }
/// <summary> /// Browser handles missing page implementation. /// </summary> /// <param name="browserType"> /// Browser type. /// </param> private void BrowserHandlesMissingPageImplementation(BrowserType browserType) { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { browserType, 1 } }; const int MaxWait = 10; using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(browserType); var stopWatch = new Stopwatch(); stopWatch.Start(); // make the request, wait for up to 10 seconds. browser.NavigateTo( "http://ieonline.microsoft.com/pinnedconfig?action=1&CurrentPage=1&itemId=1&nextQuestionId=1&nextQuestionUserId=1"); browser.WaitForPageLoad(MaxWait); stopWatch.Stop(); // expect a browser specific 404 message browser.PageSource.ShouldContain("Page not found"); stopWatch.ElapsedMilliseconds.ShouldBeLessThan((MaxWait * 1000) + 1500); } }
/// <summary> /// Browser DOM access test implementation. /// </summary> /// <param name="browserType">The type of the browser being tested.</param> private void BrowserFindElementImplementation(BrowserType browserType) { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { browserType, 1 } }; using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(browserType); browser.NavigateTo($"{Constants.VulnerabilitiesAddress}SimplePageWithForm.html"); browser.WaitForPageLoad(10); var element = browser.FindWebElement(By.Id("textInputId")); element.ShouldNotBeNull(); element.TagName.Equals("input").ShouldBeTrue(); element.SendKeys("Hello"); System.Threading.Thread.Sleep(1000); element.SendKeys(" world"); element.GetAttribute("value").Equals("Hello world").ShouldBeTrue(); element = browser.FindWebElement(By.Name("textInputName")); element.GetAttribute("value").Equals("Hello world").ShouldBeTrue(); } }
public void TestSendRequestUsingBrowserWebRequestHandlingHttpException() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; using (var browserManager = new BrowserManager(browserInstances)) { ObjectResolver.RegisterInstance <IBrowserManager>(browserManager); var context = new Context(); WebRequestContext webRequestContext = context.SendRequest(new ContextSendRequestParameter { Url = nonExistingTargetUrl, BrowserType = BrowserType.Chrome }); // check that we got the proper response back webRequestContext.ResponseHolder.ShouldNotBeNull(); webRequestContext.ResponseHolder.ResponseContent.ShouldNotBeEmpty(); webRequestContext.ResponseHolder.RequestUserAgent.ShouldEqual(BrowserType.Chrome.ToString()); webRequestContext.ResponseHolder.StatusCode.ShouldEqual(HttpStatusCode.OK); webRequestContext.ResponseHolder.BrowserPageTitle.IndexOfOi("404").ShouldBeGreaterThan(-1); } }
public void TestSendRequestUsingBrowserWebRequest() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; using (var browserManager = new BrowserManager(browserInstances)) { ObjectResolver.RegisterInstance <IBrowserManager>(browserManager); var context = new Context(); WebRequestContext webRequestContext = context.SendRequest(new ContextSendRequestParameter { Url = targetUrl, BrowserType = BrowserType.Chrome }); // check that we got the proper response back webRequestContext.ResponseHolder.ShouldNotBeNull(); webRequestContext.ResponseHolder.ResponseContent.ShouldNotBeNullOrEmpty(); webRequestContext.ResponseHolder.RequestUserAgent.ShouldContain(BrowserType.Chrome.ToString()); } }
public void TestOpenRedirectClientSideHttp() { // Setup ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; using (var browserManager = new BrowserManager(browserInstances)) { ObjectResolver.RegisterInstance <IBrowserManager>(browserManager); var target = Target.Create( $"{Constants.VulnerabilitiesAddress}PluginsTestPages/XOpenRedirectToBadPlacesHTTP.aspx?q=junk"); // Execute var vulns = ExecutePluginTestRequest(target); // Validate vulns.Count.ShouldEqual(2); vulns.ElementAt(0).Title.ShouldEqual("Open Redirect"); vulns.ElementAt(0).Evidence.ShouldEqual("www.example.com"); vulns.ElementAt(1).Title.ShouldEqual("Open Redirect"); vulns.ElementAt(1).Evidence.ShouldEqual("www.example.com"); } }
public void DomXssTestFalsePositiveResult() { const string TestUrl = @"http://www.bing.com/search?q=seattle"; var propertyBag = new ConcurrentDictionary <int, bool>(); var browserMock = CreateMockBrowser(); browserMock .Setup(m => m.NavigateTo(It.IsAny <string>())) .Callback <string>(s => propertyBag[Thread.CurrentThread.ManagedThreadId] = s.Contains("alert()")); // some pages pop their own dialog boxes, we should ignore these string alertText = "** Expected message from the page **"; browserMock .Setup(m => m.DismissedIfAlertDisplayed(out alertText)) .Returns(() => propertyBag.ContainsKey(Thread.CurrentThread.ManagedThreadId) && propertyBag[Thread.CurrentThread.ManagedThreadId]); browserMock .SetupGet(m => m.PageSource) .Returns("pagesource"); browserMock .SetupGet(m => m.Url) .Returns("http://foo"); var factoryMock = new Mock <IBrowserFactory>(); factoryMock .Setup(m => m.Create(It.IsAny <BrowserType>())) .Returns(browserMock.Object); ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserManagerMock = this.CreateBrowserManager(new[] { BrowserType.Chrome }); browserManagerMock .Setup(m => m.AcquireBrowser(It.Is <BrowserType>(b => b == BrowserType.Chrome))) .Returns(browserMock.Object); ObjectResolver.RegisterInstance(browserManagerMock.Object); var target = Target.Create(TestUrl); var context = new Context(); var instance = new TestableDomXssTest(); instance.Init(context, target); // introduce our known injection strings instance.InjectTestCaseStrings(new[] { "blah", "alert()", "foo" }); // run the test instance.DoTests(); // a vuln should be found instance.Vulnerabilities.ShouldNotBeNull(); instance.Vulnerabilities.Count.ShouldEqual(0); }
/// <summary> /// Initializes this object. /// </summary> private static void Initialize() { ObjectResolver.RegisterInstance <IPayloads>(new Payloads(Library.Constants.PayloadsQuickDataFolder)); ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; ObjectResolver.RegisterInstance <IBrowserManager>(new BrowserManager(browserInstances)); }
/// <summary> /// Browser proxy injects mandatory headers implementation. /// </summary> /// <param name="browserType"> /// Browser type. /// </param> private void BrowserProxyInjectsMandatoryHeadersImplementation(BrowserType browserType) { /* * WARNING: Terminating this test while the proxy is running can lead to adverse side effects * such as loss of web connectivity. Please allow the call to FiddlerProxy.Cleanup * to complete. */ ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { browserType, 1 } }; try { FiddlerProxy.Initialize(new[] { "TestKey:TestValue" }, Constants.FiddlerPort); using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(browserType); browser.NavigateTo($"{Constants.VulnerabilitiesAddress}dumpheaders.aspx"); browser.WaitForPageLoad(10); // Then the expected request header should be present in the page browser.PageSource.ShouldContain("TestKey : TestValue"); } // turn off the proxy and make sure the header is not injected FiddlerProxy.Initialize(new string[0], 0); using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(browserType); browser.NavigateTo($"{Constants.VulnerabilitiesAddress}dumpheaders.aspx"); browser.WaitForPageLoad(10); // Then the expected request header should be present in the page browser.PageSource.ShouldNotContain("TestKey : TestValue"); } } finally { FiddlerProxy.Cleanup(Constants.FiddlerPort); FiddlerProxy.Cleanup(0); } }
public void DomXssTestDoublePositiveResult() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; using (var browserManager = new BrowserManager(browserInstances)) { ObjectResolver.RegisterInstance <IBrowserManager>(browserManager); var target = Target.Create($"{Constants.VulnerabilitiesAddress}ShowAlert2.aspx?q=xyz"); var context = new Context(); var instance = new TestableDomXssTest(); instance.Init(context, target); // introduce our known injection strings instance.InjectTestCaseStrings(new[] { "blah" }); // run the test instance.DoTests(); // a vuln should be found instance.Vulnerabilities.ShouldNotBeNull(); instance.Vulnerabilities.Count.ShouldEqual(1); // the vuln record should be well formed var vuln = instance.Vulnerabilities.First(); vuln.Level.ShouldEqual(0); vuln.TestedParam.ShouldEqual("q"); vuln.TestedVal.ShouldEqual("blah"); vuln.Evidence.ShouldEqual("Found by Chrome"); vuln.TestPlugin.ShouldEqual("TestableDomXssTest"); vuln.Title.ShouldEqual("DOM XSS - Script injection"); // the http details should be consistent for browser generated request vuln.HttpResponse.ShouldNotBeNull(); vuln.HttpResponse.Headers.Count.ShouldEqual(0); vuln.HttpResponse.RequestHeaders.ShouldEqual(string.Empty); vuln.HttpResponse.RequestAbsolutUri.ShouldEqual($"{Constants.VulnerabilitiesAddress}ShowAlert2.aspx?q=blah"); vuln.HttpResponse.ResponseContent.ShouldNotBeNullOrEmpty(); vuln.HttpResponse.ResponseUri.ShouldNotBeNull(); vuln.HttpResponse.ResponseUri.ToString().ShouldEqual($"{Constants.VulnerabilitiesAddress}ShowAlert2.aspx?q=blah"); vuln.HttpResponse.StatusCode.ShouldEqual(HttpStatusCode.OK); vuln.HttpResponse.HttpError.ShouldEqual(string.Empty); } }
public void BrowserReportsTheCorrectProcessIdentifiersChrome() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); using (var manager = new BrowserManager(this.chromeOnly)) { var browser = manager.AcquireBrowser(BrowserType.Chrome); var browserProcesses = Process.GetProcessesByName("chrome").Select(p => p.Id); var driverprocess = Process.GetProcessesByName("chromedriver").First(); // Chrome opens separate processes for the rendering engine, plugins and each tab. browserProcesses.ShouldContain(browser.ProcessId); browser.ParentProcessId.ShouldEqual(driverprocess.Id); } }
public void TestFiddlerProxySessionFingerprint() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); const BrowserType BrowserType = BrowserType.Chrome; var browserInstances = new Dictionary <BrowserType, int> { { BrowserType, 1 } }; try { FiddlerProxy.Initialize(new string[0], Constants.FiddlerPort); using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(BrowserType); // expected headers for this browser process FiddlerProxy.RegisterInstanceHeaders( browser.ProcessId, "My User Agent 1.0", "TestKey: Process" + browser.ProcessId); browser.NavigateTo($"{Constants.VulnerabilitiesAddress}dumpheaders.aspx"); browser.WaitForPageLoad(10); // Then the expected request header should be present in the page browser.PageSource.ShouldContain("User-Agent : My User Agent 1.0"); browser.PageSource.ShouldContain("TestKey : Process" + browser.ProcessId); var fiddlerResponseSessionKey = Library.Constants.FiddlerResponseSessionKey.FormatIc( browser.ProcessId, browser.Url); // validate the proxy session fingerprint var fiddlerSession = FiddlerProxy.ResponseSession[fiddlerResponseSessionKey]; fiddlerSession.bHasResponse.ShouldBeTrue(); fiddlerSession.ResponseBody.Length.ShouldBeGreaterThan(0); fiddlerSession.oResponse.headers.Count().ShouldBeGreaterThan(0); } } finally { FiddlerProxy.Cleanup(Constants.FiddlerPort); } }
/// <summary> /// Fiddler reporting the wrong /// browser process Id when more than one instance of Chrome was present. Here we test explicitly /// for that circumstance across all browsers. /// </summary> /// <param name="browserType"> /// Browser type. /// </param> private void BrowserProxyInjectsPerRequestHeadersMultipleImplementation( BrowserType browserType) { /* * WARNING: Terminating this test while the proxy is running can lead to adverse side effects * such as loss of web connectivity. Please allow the call to FiddlerProxy.Cleanup * to complete. */ ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { browserType, 3 } }; try { FiddlerProxy.Initialize(new string[0], Constants.FiddlerPort); using (var manager = new BrowserManager(browserInstances)) { for (int i = 0; i < 3; i++) { var browser = manager.AcquireBrowser(browserType); // expected headers for this browser process FiddlerProxy.RegisterInstanceHeaders( browser.ProcessId, "My User Agent 1.0", "TestKey: Process" + browser.ProcessId); browser.NavigateTo($"{Constants.VulnerabilitiesAddress}dumpheaders.aspx"); browser.WaitForPageLoad(10); // Then the expected request header should be present in the page browser.PageSource.ShouldContain("User-Agent : My User Agent 1.0"); browser.PageSource.ShouldContain("TestKey : Process" + browser.ProcessId); } } } finally { FiddlerProxy.Cleanup(Constants.FiddlerPort); } }
/// <summary> /// The dom xss test_integration_test. /// </summary> /// <param name="browserType"> /// The browser type. /// </param> private void DomXssTestIntegrationTest(BrowserType browserType) { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { browserType, 2 } }; ObjectResolver.RegisterInstance <IBrowserManager>(new BrowserManager(browserInstances)); var target = Target.Create($"{Constants.VulnerabilitiesAddress}vuln_domxss.html?a=1"); var context = new Context(); var instance = new TestableDomXssTest(); instance.Init(context, target); // introduce our known injection strings instance.InjectTestCaseStrings(new[] { "alert(" + TestBaseHelper.AttackSignature + ")", "%22+onload=%22javascript:alert(" + TestBaseHelper.AttackSignature + ")%22" }); instance.DoTests(); // cleanly shutdown the browser manager var disposable = ObjectResolver.Resolve <IBrowserManager>() as IDisposable; Assert.IsNotNull(disposable); disposable.Dispose(); // a vuln should be found instance.Vulnerabilities.ShouldNotBeNull(); instance.Vulnerabilities.Count.ShouldEqual(1); // the vuln record should be well formed var vuln = instance.Vulnerabilities.First(); vuln.Level.ShouldEqual(0); vuln.TestedParam.ShouldEqual("a"); vuln.TestedVal.ShouldEqual("alert(" + TestBaseHelper.AttackSignature + ")"); vuln.Evidence.ShouldEqual("Found by " + browserType); vuln.TestPlugin.ShouldStartWith("TestableDomXssTest"); vuln.Title.ShouldEqual("DOM XSS - Script injection"); instance.Vulnerabilities.Count(v => v.TestPlugin == "TestableDomXssTest") .ShouldEqual(1); }
public void TestPostRequestXssNegative() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; using (var browserManager = new BrowserManager(browserInstances)) { ObjectResolver.RegisterInstance <IBrowserManager>(browserManager); // Setup var target = Target.Create("http://www.bing.com"); // Execute var vulns = ExecutePluginTestRequest(target); vulns.Count.ShouldEqual(0); } }
public void TestPostRequestXssPositive() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; using (var browserManager = new BrowserManager(browserInstances)) { ObjectResolver.RegisterInstance <IBrowserManager>(browserManager); var target = Target.Create($"{Constants.VulnerabilitiesAddress}PluginsTestPages/PostRequestXssTest.html"); // Execute var vulns = ExecutePluginTestRequest(target); vulns.Count.ShouldEqual(1); vulns.ElementAt(0).TestedVal.ShouldEqual("alert(501337)"); } }
public void TestNoOpenRedirects() { // Setup ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; using (var browserManager = new BrowserManager(browserInstances)) { ObjectResolver.RegisterInstance <IBrowserManager>(browserManager); var target = Target.Create($"{Constants.VulnerabilitiesAddress}PluginsTestPages/XNoJavascript.aspx?q=junk"); // Execute var vulns = ExecutePluginTestRequest(target); // Validate vulns.ShouldBeEmpty(); } }
/// <summary> /// Browser can add and remove cookies implementation. /// </summary> private void BrowserCanAddAndRemoveCookiesImplementation() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; var expiry = DateTime.Now.AddDays(1); using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(BrowserType.Chrome); // a new browser should have no cookies browser.AllCookies.Count.ShouldEqual(0); // adding a cookie without first loading the page should have no effect browser.AddCookie("TEST", "Hello", ".bing.com", "/", expiry); browser.AllCookies.Count.ShouldEqual(0); // navigating to a page should return some cookies // NOTE - this uses bing.com since adding cookies to localhost is problematic. browser.NavigateTo("http://bing.com"); browser.WaitForPageLoad(2000); browser.AllCookies.Count.ShouldBeGreaterThan(0); // we should be able to add and retrieve a new cookie browser.AddCookie("TEST", "Hello", ".bing.com", "/", expiry); var cookies = browser.AllCookies; var cookie = cookies["TEST"]; cookie.ShouldNotBeNull(); cookie.Value.ShouldEqual("Hello"); cookie.Path.ShouldEqual("/"); cookie.Domain.ShouldEqual(".bing.com"); // we should be able to remove all cookies browser.DeleteAllCookies(); browser.AllCookies.Count.ShouldEqual(0); } }
/// <summary> /// The browser_waits_for_a_page_with_a_slow_load_time_ implementation. /// </summary> /// <param name="browserType"> /// The browser type. /// </param> private void BrowserWaitsForAPageWithASlowLoadTimeImplementation(BrowserType browserType) { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { browserType, 1 } }; // the request will take 5 seconds to complete const int Delay = 5; using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(browserType); // make the request, wait for up to 10 seconds. browser.NavigateTo($"{Constants.VulnerabilitiesAddress}delay.html?a=" + Delay); browser.WaitForPageLoad(Constants.BrowserWaitForPageLoadInMilliseconds); // Then the page complete response should be present in the page browser.PageSource.ShouldContain("Done!"); } }
/// <summary> /// The browser_does_not_wait_for_ajax_requests_to_complete_ implementation. /// </summary> /// <param name="browserType"> /// The browser type. /// </param> private void BrowserDoesNotWaitForAjaxRequestsToCompleteImplementation(BrowserType browserType) { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { browserType, 1 } }; // the request will take 5 seconds to complete const int Delay = 5; using (var manager = new BrowserManager(browserInstances)) { var browser = manager.AcquireBrowser(browserType); // make the request, wait for up to 3 seconds. browser.NavigateTo($"{Constants.VulnerabilitiesAddress}delayajax.html?a=" + Delay); browser.WaitForPageLoad(3); // Then the AJAX response should not be present in the page browser.PageSource.ShouldNotContain("Done!"); } }
/// <summary> /// Browser does not download files implementation. /// </summary> private void BrowserDoesNotDownloadFilesImplementation() { ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserInstances = new Dictionary <BrowserType, int> { { BrowserType.Chrome, 1 } }; using (var manager = new BrowserManager(browserInstances)) { const int MaxWait = 10; var browser = manager.AcquireBrowser(BrowserType.Chrome); var stopWatch = new Stopwatch(); stopWatch.Start(); browser.NavigateTo($"{Constants.VulnerabilitiesAddress}file.js"); browser.WaitForPageLoad(MaxWait); stopWatch.Stop(); stopWatch.ElapsedMilliseconds.ShouldBeLessThan((MaxWait + 1) * 1000); } }
public void DomXssTestPositiveResult() { const string TestUrl = @"http://www.bing.com/search?q=seattle"; var propertyBag = new ConcurrentDictionary <int, bool>(); var browserMock = CreateMockBrowser(browserType: BrowserType.Chrome); browserMock .Setup(m => m.NavigateTo(It.IsAny <string>())) .Callback <string>(s => propertyBag[Thread.CurrentThread.ManagedThreadId] = s.Contains("alert(456)")); string alertText; browserMock .Setup(m => m.DismissedIfAlertDisplayed(out alertText)) .Returns(() => propertyBag.ContainsKey(Thread.CurrentThread.ManagedThreadId) && propertyBag[Thread.CurrentThread.ManagedThreadId]); browserMock .SetupGet(m => m.PageSource) .Returns("pagesource"); browserMock .SetupGet(m => m.Url) .Returns("http://foo"); browserMock .SetupGet(m => m.AlertMessageDisplayed) .Returns(new HashSet <string> { TestBaseHelper.AttackSignature }); var factoryMock = new Mock <IBrowserFactory>(); factoryMock .Setup(m => m.Create(It.IsAny <BrowserType>())) .Returns(browserMock.Object); ObjectResolver.RegisterType <IProcessManager, ProcessManager>(); var browserManagerMock = this.CreateBrowserManager(new[] { BrowserType.Chrome }); browserManagerMock .Setup(m => m.AcquireBrowser(It.Is <BrowserType>(b => b == BrowserType.Chrome))) .Returns(browserMock.Object); ObjectResolver.RegisterInstance(browserManagerMock.Object); var target = Target.Create(TestUrl); var context = new Context(); var instance = new TestableDomXssTest(); instance.Init(context, target); // introduce our known injection strings instance.InjectTestCaseStrings(new[] { "blah", "alert(" + TestBaseHelper.AttackSignature + ")", "foo" }); // run the test instance.DoTests(); // the scan should have run on multiple threads. propertyBag.Count.ShouldBeGreaterThanOrEqualTo(1); // a vuln should be found instance.Vulnerabilities.ShouldNotBeNull(); instance.Vulnerabilities.Count.ShouldEqual(3); // the vuln record should be well formed var vuln = instance.Vulnerabilities.First(t => t.TestedVal == "blah"); vuln.Level.ShouldEqual(0); vuln.TestedParam.ShouldEqual("q"); vuln.TestedVal.ShouldEqual("blah"); vuln.Evidence.ShouldEqual("Found by Chrome"); vuln.TestPlugin.ShouldEqual("TestableDomXssTest"); vuln.Title.ShouldEqual("DOM XSS - Script injection"); // the http details should be consistent for browser generated request vuln.HttpResponse.ShouldNotBeNull(); vuln.HttpResponse.Headers.Count.ShouldEqual(0); vuln.HttpResponse.RequestHeaders.ShouldEqual(string.Empty); vuln.HttpResponse.RequestAbsolutUri.ShouldEqual("http://www.bing.com/search?q=blah"); vuln.HttpResponse.RequestHost.ShouldEqual("www.bing.com"); vuln.HttpResponse.ResponseContent.ShouldEqual(browserMock.Object.PageSource); vuln.HttpResponse.ResponseUri.ShouldNotBeNull(); vuln.HttpResponse.ResponseUri.ToString().ShouldEqual("http://foo/"); vuln.HttpResponse.StatusCode.ShouldEqual(HttpStatusCode.OK); vuln.HttpResponse.HttpError.ShouldEqual(string.Empty); // the browser requested all of the expected urls, even after a vuln was found browserMock.Verify(m => m.NavigateTo(It.Is <string>(u => u == @"http://www.bing.com/search?q=blah")), Times.Once()); browserMock.Verify(m => m.NavigateTo(It.Is <string>(u => u == @"http://www.bing.com/search?q=alert(" + TestBaseHelper.AttackSignature + ")")), Times.Once()); browserMock.Verify(m => m.NavigateTo(It.Is <string>(u => u == @"http://www.bing.com/search?q=foo")), Times.Once()); }