From 69f39ee9e53f3a5f043dd8471c1531bde320ca85 Mon Sep 17 00:00:00 2001 From: Simon Bennetts Date: Mon, 5 Feb 2024 17:33:28 +0000 Subject: [PATCH] Authhelper: trad app auth detection improvements Signed-off-by: Simon Bennetts --- addOns/authhelper/CHANGELOG.md | 5 ++++ .../zaproxy/addon/authhelper/AuthUtils.java | 30 ++++++++++++++++++- .../BrowserBasedAuthenticationMethodType.java | 3 ++ .../addon/authhelper/AuthUtilsUnitTest.java | 26 ++++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/addOns/authhelper/CHANGELOG.md b/addOns/authhelper/CHANGELOG.md index c0c488c3f21..7df034d0567 100644 --- a/addOns/authhelper/CHANGELOG.md +++ b/addOns/authhelper/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this add-on will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased + +### Changed +- Handle traditional apps better in authentication detection dialog. +- Make cookies set in auth request available to header based session management. + ### Fixed - Correct HTTP field names shown in diagnostic data. diff --git a/addOns/authhelper/src/main/java/org/zaproxy/addon/authhelper/AuthUtils.java b/addOns/authhelper/src/main/java/org/zaproxy/addon/authhelper/AuthUtils.java index f3c990c3fb7..feea1f8621c 100644 --- a/addOns/authhelper/src/main/java/org/zaproxy/addon/authhelper/AuthUtils.java +++ b/addOns/authhelper/src/main/java/org/zaproxy/addon/authhelper/AuthUtils.java @@ -204,13 +204,19 @@ static WebElement getPasswordField(List inputElements) { * Authenticate as the given user, by filling in and submitting the login form * * @param wd the WebDriver controlling the browser + * @param context the context which is being used for authentication * @param loginPageUrl the URL of the login page * @param username the username * @param password the password * @return true if the login form was successfully submitted. */ public static boolean authenticateAsUser( - WebDriver wd, String loginPageUrl, String username, String password, int waitInSecs) { + WebDriver wd, + Context context, + String loginPageUrl, + String username, + String password, + int waitInSecs) { wd.get(loginPageUrl); sleep(50); if (demoMode) { @@ -278,6 +284,15 @@ public static boolean authenticateAsUser( incStatsCounter(loginPageUrl, AUTH_BROWSER_PASSED_STATS); AuthUtils.sleep(TimeUnit.SECONDS.toMillis(waitInSecs)); + if (context != null) { + if (context.getAuthenticationMethod().getPollUrl() == null) { + // We failed to identify a suitable URL for polling. + // This can happen for more traditional apps - refresh the current one in case + // its a good option. + wd.get(wd.getCurrentUrl()); + AuthUtils.sleep(TimeUnit.SECONDS.toMillis(1)); + } + } return true; } if (userField == null) { @@ -514,6 +529,16 @@ protected static Map getAllTokens(HttpMessage msg) { p.getName(), p.getValue()))); // Add Cookies + msg.getRequestHeader() + .getCookieParams() + .forEach( + c -> + addToMap( + tokens, + new SessionToken( + SessionToken.COOKIE_SOURCE, + c.getName(), + c.getValue()))); msg.getResponseHeader() .getHttpCookies(null) .forEach( @@ -731,12 +756,14 @@ static class AuthenticationBrowserHook implements BrowserHook { private BrowserBasedAuthenticationMethod bbaMethod; private UsernamePasswordAuthenticationCredentials userCreds; + private Context context; AuthenticationBrowserHook(Context context, String userName) { this(context, getUser(context, userName)); } AuthenticationBrowserHook(Context context, User user) { + this.context = context; AuthenticationMethod method = context.getAuthenticationMethod(); if (!(method instanceof BrowserBasedAuthenticationMethod)) { throw new IllegalStateException("Unsupported method " + method.getType().getName()); @@ -757,6 +784,7 @@ public void browserLaunched(SeleniumScriptUtils ssutils) { "AuthenticationBrowserHook - authenticating as {}", userCreds.getUsername()); AuthUtils.authenticateAsUser( ssutils.getWebDriver(), + context, bbaMethod.getLoginPageUrl(), userCreds.getUsername(), userCreds.getPassword(), diff --git a/addOns/authhelper/src/main/java/org/zaproxy/addon/authhelper/BrowserBasedAuthenticationMethodType.java b/addOns/authhelper/src/main/java/org/zaproxy/addon/authhelper/BrowserBasedAuthenticationMethodType.java index fe7944d387b..80f111084ad 100644 --- a/addOns/authhelper/src/main/java/org/zaproxy/addon/authhelper/BrowserBasedAuthenticationMethodType.java +++ b/addOns/authhelper/src/main/java/org/zaproxy/addon/authhelper/BrowserBasedAuthenticationMethodType.java @@ -339,6 +339,8 @@ public WebSession authenticate( .getExtensionLoader() .getExtension(ExtensionSelenium.class); + Context context = Model.getSingleton().getSession().getContext(user.getContextId()); + try { proxyPort = getProxy(user.getContext()).start(proxyHost, 0); @@ -353,6 +355,7 @@ public WebSession authenticate( if (AuthUtils.authenticateAsUser( wd, + context, loginPageUrl, userCreds.getUsername(), userCreds.getPassword(), diff --git a/addOns/authhelper/src/test/java/org/zaproxy/addon/authhelper/AuthUtilsUnitTest.java b/addOns/authhelper/src/test/java/org/zaproxy/addon/authhelper/AuthUtilsUnitTest.java index 6ca084abd51..5d0c1ef2f56 100644 --- a/addOns/authhelper/src/test/java/org/zaproxy/addon/authhelper/AuthUtilsUnitTest.java +++ b/addOns/authhelper/src/test/java/org/zaproxy/addon/authhelper/AuthUtilsUnitTest.java @@ -346,6 +346,32 @@ void shouldExtractJsonTokens() throws Exception { assertThat(tokens.get("header:Content-Type").getValue(), is(equalTo("application/json"))); } + @Test + void shouldExtractCookies() throws Exception { + // Given + HttpMessage msg = + new HttpMessage( + new HttpRequestHeader( + "GET https://example.com/ HTTP/1.1\r\n" + + "Host: example.com\r\n" + + "Cookie: aaa=bbb\r\n\r\n"), + new HttpRequestBody("Request Body"), + new HttpResponseHeader( + "HTTP/1.1 200 OK\r\n" + "Set-Cookie: ccc=ddd; HttpOnly; Secure"), + new HttpResponseBody("Response Body")); + // When + Map tokens = AuthUtils.getAllTokens(msg); + + // Then + System.out.println(tokens); + assertThat(tokens.size(), is(equalTo(3))); + assertThat(tokens.get("cookie:aaa").getValue(), is(equalTo("bbb"))); + assertThat(tokens.get("cookie:ccc").getValue(), is(equalTo("ddd"))); + assertThat( + tokens.get("header:Set-Cookie").getValue(), + is(equalTo("ccc=ddd; HttpOnly; Secure"))); + } + @Test void shouldGetEmptyHeaderTokens() throws Exception { // Given