From 0410f3c4d9b39b754a2203a29834cac51da11258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Op=C3=A1lka?= Date: Fri, 19 Jan 2024 19:52:31 +0100 Subject: [PATCH] [UNDERTOW-2264] CVE-2023-1973 Force session timeout to 2 minutes when session was created during the authentication phase. Once authentication is complete restore original (configured) session timeout. Signed-off-by: Flavia Rainone Origin: https://github.com/undertow-io/undertow/commit/0410f3c4d9b39b754a2203a29834cac51da11258 --- .../impl/FormAuthenticationMechanism.java | 28 +++++++++++++++++-- .../ServletFormAuthenticationMechanism.java | 20 ++++++++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/io/undertow/security/impl/FormAuthenticationMechanism.java b/core/src/main/java/io/undertow/security/impl/FormAuthenticationMechanism.java index 22f95a6..5e6981e 100644 --- a/core/src/main/java/io/undertow/security/impl/FormAuthenticationMechanism.java +++ b/core/src/main/java/io/undertow/security/impl/FormAuthenticationMechanism.java @@ -45,9 +45,8 @@ import static io.undertow.UndertowMessages.MESSAGES; public class FormAuthenticationMechanism implements AuthenticationMechanism { public static final String LOCATION_ATTRIBUTE = FormAuthenticationMechanism.class.getName() + ".LOCATION"; - public static final String DEFAULT_POST_LOCATION = "/j_security_check"; - + protected static final String ORIGINAL_SESSION_TIMEOUT = "io.undertow.servlet.form.auth.orig.session.timeout";; private final String name; private final String loginPage; private final String errorPage; @@ -55,6 +54,13 @@ public class FormAuthenticationMechanism implements AuthenticationMechanism { private final FormParserFactory formParserFactory; private final IdentityManager identityManager; + /** + * If the authentication process creates a session, this is the maximum session timeout (in seconds) during the + * authentication process. Once authentication is complete, the default session timeout will apply. Sessions that + * exist before the authentication process starts will retain their original session timeout throughout. + */ + protected final int authenticationSessionTimeout = 120; + public FormAuthenticationMechanism(final String name, final String loginPage, final String errorPage) { this(FormParserFactory.builder().build(), name, loginPage, errorPage); } @@ -144,6 +150,10 @@ public class FormAuthenticationMechanism implements AuthenticationMechanism { protected void handleRedirectBack(final HttpServerExchange exchange) { final Session session = Sessions.getSession(exchange); if (session != null) { + final Integer originalSessionTimeout = (Integer) session.removeAttribute(ORIGINAL_SESSION_TIMEOUT); + if (originalSessionTimeout != null) { + session.setMaxInactiveInterval(originalSessionTimeout); + } final String location = (String) session.removeAttribute(LOCATION_ATTRIBUTE); if(location != null) { exchange.addDefaultResponseListener(new DefaultResponseListener() { @@ -179,7 +189,19 @@ public class FormAuthenticationMechanism implements AuthenticationMechanism { } protected void storeInitialLocation(final HttpServerExchange exchange) { - Session session = Sessions.getOrCreateSession(exchange); + Session session = Sessions.getSession(exchange); + boolean newSession = false; + if (session == null) { + session = Sessions.getOrCreateSession(exchange); + newSession = true; + } + if (newSession) { + int originalMaxInactiveInterval = session.getMaxInactiveInterval(); + if (originalMaxInactiveInterval > authenticationSessionTimeout) { + session.setAttribute(ORIGINAL_SESSION_TIMEOUT, session.getMaxInactiveInterval()); + session.setMaxInactiveInterval(authenticationSessionTimeout); + } + } session.setAttribute(LOCATION_ATTRIBUTE, RedirectBuilder.redirect(exchange, exchange.getRelativePath())); } diff --git a/servlet/src/main/java/io/undertow/servlet/handlers/security/ServletFormAuthenticationMechanism.java b/servlet/src/main/java/io/undertow/servlet/handlers/security/ServletFormAuthenticationMechanism.java index 9c5c704..51a0b68 100644 --- a/servlet/src/main/java/io/undertow/servlet/handlers/security/ServletFormAuthenticationMechanism.java +++ b/servlet/src/main/java/io/undertow/servlet/handlers/security/ServletFormAuthenticationMechanism.java @@ -30,6 +30,7 @@ import io.undertow.server.session.Session; import io.undertow.servlet.handlers.ServletRequestContext; import io.undertow.servlet.spec.HttpSessionImpl; import io.undertow.servlet.util.SavedRequest; +import io.undertow.servlet.spec.ServletContextImpl; import io.undertow.util.Headers; import io.undertow.util.RedirectBuilder; @@ -120,13 +121,26 @@ public class ServletFormAuthenticationMechanism extends FormAuthenticationMechan return; } final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); - HttpSessionImpl httpSession = servletRequestContext.getCurrentServletContext().getSession(exchange, true); + final ServletContextImpl servletContextImpl = servletRequestContext.getCurrentServletContext(); + HttpSessionImpl httpSession = servletContextImpl.getSession(exchange, false); + boolean newSession = false; + if (httpSession == null) { + httpSession = servletContextImpl.getSession(exchange, true); + newSession = true; + } Session session; if (System.getSecurityManager() == null) { session = httpSession.getSession(); } else { session = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(httpSession)); } + if (newSession) { + int originalMaxInactiveInterval = session.getMaxInactiveInterval(); + if (originalMaxInactiveInterval > authenticationSessionTimeout) { + session.setAttribute(ORIGINAL_SESSION_TIMEOUT, session.getMaxInactiveInterval()); + session.setMaxInactiveInterval(authenticationSessionTimeout); + } + } session.setAttribute(SESSION_KEY, RedirectBuilder.redirect(exchange, exchange.getRelativePath())); SavedRequest.trySaveRequest(exchange); } @@ -143,6 +157,10 @@ public class ServletFormAuthenticationMechanism extends FormAuthenticationMechan } else { session = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(httpSession)); } + Integer originalSessionTimeout = (Integer) session.removeAttribute(ORIGINAL_SESSION_TIMEOUT); + if (originalSessionTimeout != null) { + session.setMaxInactiveInterval(originalSessionTimeout); + } String path = (String) session.getAttribute(SESSION_KEY); if (path != null) { try { -- 2.46.2