CVE-2023-1973
Description
A flaw was found in Undertow package. Using the FormAuthenticationMechanism, a malicious user could trigger a Denial of Service by sending crafted requests, leading the server to an OutofMemory error, exhausting the server's memory.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
io.undertow:undertow-coreMaven | < 2.2.32.Final | 2.2.32.Final |
io.undertow:undertow-coreMaven | >= 2.3.0.Alpha1, < 2.3.13.Final | 2.3.13.Final |
Patches
20410f3c4d9b3[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.
2 files changed · +44 −4
core/src/main/java/io/undertow/security/impl/FormAuthenticationMechanism.java+25 −3 modified@@ -46,16 +46,22 @@ 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; private final String postLocation; 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); } @@ -166,6 +172,10 @@ public AuthenticationMechanismOutcome runFormAuth(final HttpServerExchange excha 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() { @@ -208,7 +218,19 @@ public ChallengeResult sendChallenge(final HttpServerExchange exchange, final Se } 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())); }
servlet/src/main/java/io/undertow/servlet/handlers/security/ServletFormAuthenticationMechanism.java+19 −1 modified@@ -32,6 +32,7 @@ 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; @@ -195,13 +196,26 @@ protected void storeInitialLocation(final HttpServerExchange exchange, byte[] by 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); + } + } SessionManager manager = session.getSessionManager(); if (seenSessionManagers.add(manager)) { manager.registerSessionListener(LISTENER); @@ -226,6 +240,10 @@ protected void handleRedirectBack(final HttpServerExchange exchange) { } 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 || overrideInitial) && defaultPage != null) { path = defaultPage;
b289b18bc0ba[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.
2 files changed · +44 −4
core/src/main/java/io/undertow/security/impl/FormAuthenticationMechanism.java+25 −3 modified@@ -46,16 +46,22 @@ 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; private final String postLocation; 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); } @@ -166,6 +172,10 @@ public AuthenticationMechanismOutcome runFormAuth(final HttpServerExchange excha 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() { @@ -208,7 +218,19 @@ public ChallengeResult sendChallenge(final HttpServerExchange exchange, final Se } 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())); }
servlet/src/main/java/io/undertow/servlet/handlers/security/ServletFormAuthenticationMechanism.java+19 −1 modified@@ -32,6 +32,7 @@ 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; @@ -195,13 +196,26 @@ protected void storeInitialLocation(final HttpServerExchange exchange, byte[] by 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); + } + } SessionManager manager = session.getSessionManager(); if (seenSessionManagers.add(manager)) { manager.registerSessionListener(LISTENER); @@ -226,6 +240,10 @@ protected void handleRedirectBack(final HttpServerExchange exchange) { } 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 || overrideInitial) && defaultPage != null) { path = defaultPage;
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
12- github.com/advisories/GHSA-97cq-f4jm-mv8hghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-1973ghsaADVISORY
- access.redhat.com/errata/RHSA-2024:1674nvdWEB
- access.redhat.com/errata/RHSA-2024:1675nvdWEB
- access.redhat.com/errata/RHSA-2024:1676nvdWEB
- access.redhat.com/errata/RHSA-2024:1677nvdWEB
- access.redhat.com/errata/RHSA-2024:2763nvdWEB
- access.redhat.com/errata/RHSA-2024:2764nvdWEB
- access.redhat.com/security/cve/CVE-2023-1973nvdWEB
- bugzilla.redhat.com/show_bug.cginvdWEB
- github.com/undertow-io/undertow/commit/0410f3c4d9b39b754a2203a29834cac51da11258ghsaWEB
- github.com/undertow-io/undertow/commit/b289b18bc0ba40c134698a430c70ca1835c51d78ghsaWEB
News mentions
0No linked articles in our index yet.