/// <summary> /// The check for unexpected dialog. /// </summary> /// <param name="uri"> /// The uri. /// </param> /// <param name="browser"> /// The browser. /// </param> /// <param name="exception"> /// The exception. /// </param> private static void CheckForUnexpectedDialog(Uri uri, BrowserAbstract browser, Exception exception) { if (browser != null && (exception.Message.Contains("unexpected alert open") || (exception.InnerException != null && exception.InnerException.Message.Contains("unexpected alert open")))) { // ReSharper disable once RedundantAssignment string text = string.Empty; var visible = browser.DismissedIfAlertDisplayed(out text); // did we miss a vuln? if (string.IsNullOrEmpty(text)) { Logger.WriteError( "Context: Missed a vuln? Browser {0} (PID {1}) threw UnhandledAlertException at {2}, verified {3} text '{4}'", browser.BrowserType.ToString(), browser.ProcessId, uri.OriginalString, visible, text); } } }
/// <summary> /// The check for vulnerabilities. /// </summary> /// <param name="browser"> /// The browser. /// </param> /// <param name="testCase"> /// The testCase. /// </param> /// <param name="testValue"> /// The tested val. /// </param> private void CheckForVulnerabilities( BrowserAbstract browser, TestCase testCase, string testValue) { // waiting for page to load browser.WaitForPageLoad(5000); string alertText; browser.DismissedIfAlertDisplayed(out alertText); if (browser.AlertMessageDisplayed.Contains(TestBaseHelper.AttackSignature)) { // since we use the same browser instance clear the alerts after the issue has been logged browser.AlertMessageDisplayed.Clear(); // we found one issue this.vulnerabilityFound = true; Vulnerabilities.Enqueue(new Vulnerability { Title = testCase.TestName, Level = (int)VulnerabilityLevelEnum.High, TestedParam = string.Empty, TestedVal = testValue, Evidence = "Found by {0}".FormatIc(browser.BrowserType.ToString()), MatchString = testCase.MatchString, TestPlugin = GetType().Name }); } }
/// <summary> /// The send payload. /// </summary> /// <param name="postElement"> /// The post element. /// </param> /// <param name="payload"> /// The payload. /// </param> /// <param name="browser"> /// The browser. /// </param> /// <param name="testCase"> /// The test case. /// </param> private void SendPayload(IWebElement postElement, string payload, BrowserAbstract browser, TestCase testCase) { if (!postElement.Displayed) { Logger.WriteWarning( "Element {0} not displayed, url ={1}", GetElementIdentification(postElement), this.TestTarget.Uri.OriginalString); return; } // send payload postElement.SendKeys(payload); // send enter postElement.SendKeys(Keys.Return); // waiting for page to load browser.WaitForPageLoad(5000); // dismiss any present alert string alertText; browser.DismissedIfAlertDisplayed(out alertText); // log xss vulnerabilities this.CheckForVulnerabilities(browser, testCase, payload); }
/// <summary> /// The release browser. /// </summary> /// <param name="browser"> /// The browser. /// </param> public static void ReleaseBrowser(BrowserAbstract browser) { if (browser != null) { var browserManager = ObjectResolver.Resolve <IBrowserManager>(); browserManager.ReleaseBrowser(browser); } }
/// <summary> /// The inspect. /// </summary> /// <param name="target"> /// The target. /// </param> /// <param name="browser"> /// The browser. /// </param> /// <returns> /// An enumerator that allows foreach to be used to process inspect in this collection. /// </returns> public IEnumerable <IWebElement> Inspect(ITarget target, ref BrowserAbstract browser) { // clear the container in case we reuse the object this.inputElement.Clear(); if (browser == null) { BrowserAbstract closureBrowser = this.context.AcquireBrowser(BrowserType.Chrome); browser = closureBrowser; if (browser == null) { Logger.Logger.WriteWarning("Not able to acquire a browser"); return(this.inputElement); } } browser.NavigateTo(target.Uri.OriginalString); // waiting for page to load browser.WaitForPageLoad(Common.Constants.BrowserWaitForPageLoadInMilliseconds); // dismiss any alert and register the text message, catch the vulnerability in the test plugin string alertText; browser.DismissedIfAlertDisplayed(out alertText); foreach (var pathElement in this.xPathElements) { IEnumerable <IWebElement> elements = browser.FindWebElements(By.XPath(pathElement)); foreach (IWebElement webElement in elements) { this.inputElement.Add(webElement); } } return(this.inputElement); }
/// <inheritdoc /> public BrowserAbstract AcquireBrowser(BrowserType browserType) { var browserManager = ObjectResolver.Resolve <IBrowserManager>(); // there is no browser pool created if (browserManager.AvailableBrowserTypes.All(t => t != browserType)) { throw new ArgumentException( $"There is no browser pool created for type {browserType}.", browserType.ToString()); } // try to acquire a browser BrowserAbstract browser = browserManager.AcquireBrowser(browserType); if (browser == null) { throw new ArgumentException( "Browser type {0} not available.".FormatIc(browserType.ToString()), browserType.ToString()); } return(browser); }
/// <summary> /// Browser navigate to page. /// </summary> /// <param name="contextSendRequestParameter"> /// The context send request parameter. /// </param> /// <param name="uri"> /// The uri. /// </param> /// <param name="webRequestContext"> /// The web request context. /// </param> private void BrowserNavigateToPage( ContextSendRequestParameter contextSendRequestParameter, Uri uri, WebRequestContext webRequestContext) { webRequestContext.ResponseHolder = new HttpWebResponseHolder(); BrowserAbstract browser = null; try { var browserManager = ObjectResolver.Resolve <IBrowserManager>(); // there is no browser pool created for this browser type if (browserManager.AvailableBrowserTypes.All(t => t != contextSendRequestParameter.BrowserType)) { return; } // try to acquire a browser if we don't have one already browser = webRequestContext.Browser ?? browserManager.AcquireBrowser(contextSendRequestParameter.BrowserType); if (browser == null) { Library.Logger.Logger.WriteWarning( "Browser pool failed allocation (measured by BrowserPoolCounters.FailedAllocationsPerMinute)."); return; } // in case we acquired then set this in the request context webRequestContext.Browser = browser; // Add request cookies. if (this.CurrentCookies.ContainsKey(uri.Host)) { foreach (Cookie cookie in this.CurrentCookies[uri.Host]) { browser.AddCookie(cookie.Name, cookie.Value, cookie.Domain, cookie.Path, cookie.Expires); } } var stopWatch = new Stopwatch(); stopWatch.Start(); browser.NavigateTo(uri.OriginalString); stopWatch.Stop(); // FireFox does not block on the presence of an alert dialog, so we manually check here. string alertText; browser.DismissedIfAlertDisplayed(out alertText); browser.WaitForPageLoad(Constants.BrowserWaitForPageLoadInMilliseconds); // check for messages again following page load - do this before querying other browser properties browser.DismissedIfAlertDisplayed(out alertText); var fiddlerResponseSessionKey = Library.Constants.FiddlerResponseSessionKey.FormatIc( browser.ProcessId, browser.Url); // get fiddler response var fiddlerResponse = FiddlerProxy.ResponseSession.ContainsKey(fiddlerResponseSessionKey) ? FiddlerProxy.ResponseSession[fiddlerResponseSessionKey].oResponse : null; var fiddlerRequest = FiddlerProxy.ResponseSession.ContainsKey(fiddlerResponseSessionKey) ? FiddlerProxy.ResponseSession[fiddlerResponseSessionKey].oRequest : null; // populate response holder webRequestContext.ResponseHolder.StatusCode = fiddlerResponse != null ? (HttpStatusCode)fiddlerResponse.headers.HTTPResponseCode : HttpStatusCode.OK; var source = browser.PageSource; webRequestContext.ResponseHolder.ResponseContent = source; webRequestContext.ResponseHolder.RequestAbsolutUri = uri.AbsoluteUri; webRequestContext.ResponseHolder.RequestHost = uri.Host; Uri resultUri; if (Uri.TryCreate(browser.Url, UriKind.Absolute, out resultUri)) { webRequestContext.ResponseHolder.ResponseUri = resultUri; } webRequestContext.ResponseHolder.ResponseDateTime = DateTime.UtcNow; webRequestContext.ResponseHolder.RequestUserAgent = contextSendRequestParameter.BrowserType.ToString(); webRequestContext.ResponseHolder.BrowserPageTitle = browser.PageTitle; webRequestContext.ResponseHolder.ResponseContentType = "text/html"; webRequestContext.ResponseHolder.Latency = new TimeSpan(0, 0, 0, 0, (int)stopWatch.Elapsed.TotalMilliseconds); // set headers from fiddler for this request if (fiddlerRequest != null) { webRequestContext.ResponseHolder.RequestHeaders = Regex.Replace(fiddlerRequest.headers.ToString().Trim(), @"[\u0000-\u001F]", string.Empty); } // set headers from fiddler for this response if (fiddlerResponse != null) { webRequestContext.ResponseHolder.SetResponseFiddlerHeaders(fiddlerResponse.headers); } // set back response cookies webRequestContext.ResponseHolder.Cookies = browser.AllCookies; } catch (Exception exception) { webRequestContext.ResponseHolder.HttpError = exception.Message; CheckForUnexpectedDialog(uri, browser, exception); } }
/// <summary> /// Override the do tests function, since it has the default get request behavior.Executes the tests. /// </summary> /// <seealso cref="M:BackScatterScannerLib.Engine.TestBase.DoTests()"/> public override void DoTests() { BrowserAbstract browser = null; var postElements = this.inspectPostPage.Inspect(this.TestTarget, ref browser).ToArray(); // a container representing the id of the element and the element itself var webElementsToBeTested = new Dictionary <string, IWebElement>(); foreach (var postElement in postElements) { string elementUniqueIdentification = GetElementIdentification(postElement); webElementsToBeTested[elementUniqueIdentification] = postElement; } try { // test all user interaction controls while (webElementsToBeTested.Count > 0) { // if we found a vulnerability then exit, the page is already compromised if (this.vulnerabilityFound) { break; } // take the first element and start testing KeyValuePair <string, IWebElement> postElement = webElementsToBeTested.First(); // for each test case foreach (var testCase in this.TestCases) { // if we found a vulnerability then exit, the page is already compromised if (this.vulnerabilityFound) { break; } if (string.IsNullOrEmpty(postElement.Key)) { break; } // for each payload in the test case foreach (var payload in testCase.InjectionString) { // if we found a vulnerability then exit, the page is already compromised if (this.vulnerabilityFound) { break; } try { this.SendPayload(postElement.Value, payload, browser, testCase); } catch (StaleElementReferenceException ex) { // before re-inspecting the page check for vulnerabilities this.CheckForVulnerabilities(browser, testCase, payload); // the web elements had become stale the refresh them, re- inspect the elements and continue testing postElements = this.inspectPostPage.Inspect(this.TestTarget, ref browser).ToArray(); // update the new reflected elements var newWebElements = this.UpdateWebElementsToBeTested( webElementsToBeTested, postElements); webElementsToBeTested.Clear(); webElementsToBeTested.AddRange(newWebElements); postElement = webElementsToBeTested.SingleOrDefault( e => e.Key.Equals(postElement.Key, StringComparison.InvariantCultureIgnoreCase)); if (string.IsNullOrEmpty(postElement.Key)) { break; } Logger.WriteWarning(ex); } catch (UnhandledAlertException ex) { this.CheckForVulnerabilities(browser, testCase, payload); Logger.WriteError(ex); } catch (Exception ex) { Logger.WriteError(ex); } } } if (!string.IsNullOrEmpty(postElement.Key)) { // after the testing is done remove it from container webElementsToBeTested.Remove(postElement.Key); } } } finally { Context.ReleaseBrowser(browser); } }