This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.1.x by this push:
     new fe6ffca0a3 Harden FORM authentication by limiting session duration
fe6ffca0a3 is described below

commit fe6ffca0a31fc59a57fcbfec5c948c61786d7ce8
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Mar 9 10:25:00 2023 +0000

    Harden FORM authentication by limiting session duration
    
    If the session is created by the FORM authentication process, limit the
    duration of the session (120s by default) to limit the time the saved
    request body must be retained.
---
 .../catalina/authenticator/FormAuthenticator.java  | 45 +++++++++++++++++++++-
 .../catalina/authenticator/SavedRequest.java       | 15 ++++++++
 webapps/docs/changelog.xml                         |  7 ++++
 webapps/docs/config/valve.xml                      |  7 ++++
 webapps/docs/security-howto.xml                    | 12 ++++--
 5 files changed, 82 insertions(+), 4 deletions(-)

diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java 
b/java/org/apache/catalina/authenticator/FormAuthenticator.java
index 5abdb07998..2876a2d04c 100644
--- a/java/org/apache/catalina/authenticator/FormAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java
@@ -27,6 +27,7 @@ import jakarta.servlet.RequestDispatcher;
 import jakarta.servlet.http.Cookie;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
 
 import org.apache.catalina.Realm;
 import org.apache.catalina.Session;
@@ -68,6 +69,13 @@ public class FormAuthenticator extends AuthenticatorBase {
      */
     protected String landingPage = null;
 
+    /**
+     * 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 int authenticationSessionTimeout = 120;
+
 
     // ------------------------------------------------------------- Properties
 
@@ -111,9 +119,32 @@ public class FormAuthenticator extends AuthenticatorBase {
     }
 
 
-    // ------------------------------------------------------ Protected Methods
+    /**
+     * Returns the maximum session timeout to be used during authentication if 
the authentication process creates a
+     * session.
+     *
+     * @return the maximum session timeout to be used during authentication if 
the authentication process creates a
+     *             session
+     */
+    public int getAuthenticationSessionTimeout() {
+        return authenticationSessionTimeout;
+    }
 
 
+    /**
+     * Configures the maximum session timeout to be used during authentication 
if the authentication process creates a
+     * session.
+     *
+     * @param authenticationSessionTimeout The maximum session timeout to use 
duriing authentication if the
+     *                                         authentication process creates 
a session
+     */
+    public void setAuthenticationSessionTimeout(int 
authenticationSessionTimeout) {
+        this.authenticationSessionTimeout = authenticationSessionTimeout;
+    }
+
+
+    // ------------------------------------------------------ Protected Methods
+
     /**
      * Authenticate the user making this request, based on the specified login 
configuration. Return <code>true</code>
      * if any specified constraint has been satisfied, or <code>false</code> 
if we have created a response challenge
@@ -616,6 +647,10 @@ public class FormAuthenticator extends AuthenticatorBase {
         request.getQueryString();
         request.getProtocol();
 
+        if (saved.getOriginalMaxInactiveInterval() > 0) {
+            
session.setMaxInactiveInterval(saved.getOriginalMaxInactiveInterval());
+        }
+
         return true;
     }
 
@@ -681,6 +716,14 @@ public class FormAuthenticator extends AuthenticatorBase {
         saved.setRequestURI(request.getRequestURI());
         saved.setDecodedRequestURI(request.getDecodedRequestURI());
 
+        if (session instanceof HttpSession && ((HttpSession) session).isNew()) 
{
+            int originalMaxInactiveInterval = session.getMaxInactiveInterval();
+            if (originalMaxInactiveInterval > 
getAuthenticationSessionTimeout()) {
+                
saved.setOriginalMaxInactiveInterval(originalMaxInactiveInterval);
+                
session.setMaxInactiveInterval(getAuthenticationSessionTimeout());
+            }
+        }
+
         // Stash the SavedRequest in our session for later use
         session.setNote(Constants.FORM_REQUEST_NOTE, saved);
     }
diff --git a/java/org/apache/catalina/authenticator/SavedRequest.java 
b/java/org/apache/catalina/authenticator/SavedRequest.java
index c82a4d7a8c..8b9f08b618 100644
--- a/java/org/apache/catalina/authenticator/SavedRequest.java
+++ b/java/org/apache/catalina/authenticator/SavedRequest.java
@@ -163,6 +163,7 @@ public final class SavedRequest implements Serializable {
         this.body = body;
     }
 
+
     /**
      * The content type of the request, used if this is a POST.
      */
@@ -175,4 +176,18 @@ public final class SavedRequest implements Serializable {
     public void setContentType(String contentType) {
         this.contentType = contentType;
     }
+
+
+    /**
+     * The original maxInactiveInterval for the session.
+     */
+    private int originalMaxInactiveInterval = -1;
+
+    public int getOriginalMaxInactiveInterval() {
+        return originalMaxInactiveInterval;
+    }
+
+    public void setOriginalMaxInactiveInterval(int 
originalMaxInactiveInterval) {
+        this.originalMaxInactiveInterval = originalMaxInactiveInterval;
+    }
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index a2bec27624..e4a51ba2cf 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -116,6 +116,13 @@
         Add an access log valve that uses a json format. Based on pull request
         <pr>539</pr> provided by Thomas Meyer. (remm)
       </add>
+      <add>
+        Harden the FORM authentication process against DoS attacks by using a
+        reduced session timeout if the FORM authentication process creates a
+        session. The duration of this timeout is configured by the
+        <code>authenticationSessionTimeout</code> attribute of the FORM
+        authenticator. (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Coyote">
diff --git a/webapps/docs/config/valve.xml b/webapps/docs/config/valve.xml
index 35c1f3f3ac..dbec996c45 100644
--- a/webapps/docs/config/valve.xml
+++ b/webapps/docs/config/valve.xml
@@ -1752,6 +1752,13 @@
         value is <code>never</code>.</p>
       </attribute>
 
+      <attribute name="authenticationSessionTimeout" required="false">
+        <p>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. If not
+        set, the default value of <code>120</code> seconds will be used.</p>
+      </attribute>
+
       <attribute name="changeSessionIdOnAuthentication" required="false">
         <p>Controls if the session ID is changed if a session exists at the
         point where users are authenticated. This is to prevent session 
fixation
diff --git a/webapps/docs/security-howto.xml b/webapps/docs/security-howto.xml
index 73c228000e..ffbc5bc7e6 100644
--- a/webapps/docs/security-howto.xml
+++ b/webapps/docs/security-howto.xml
@@ -295,9 +295,15 @@
 
       <p>The <strong>maxSavePostSize</strong> attribute controls the saving of
       the request body during FORM and CLIENT-CERT authentication and HTTP/1.1
-      upgrade. For FORM authentication, the request body is cached for the
-      duration of the authentication (which may be many minutes) so this is
-      limited to 4KB by default to reduce exposure to a DOS attack.</p>
+      upgrade. For FORM authentication, the request body is cached in the HTTP
+      session for the duration of the authentication so the cached request body
+      is limited to 4KB by default to reduce exposure to a DOS attack. To
+      further reduce exposure to a DoS attack by limiting the permitted 
duration
+      of the FORM authentication, a reduced session timeout is used if the
+      session is created by the FORM authentication. This reduced timeout is
+      controlled by the <code>authenticationSessionTimeout</code> attribute of
+      the <a href="config/valve.html#Form_Authenticator_Valve">FORM
+      authenticator</a>.</p>
 
       <p>The <strong>maxParameterCount</strong> attribute controls the maximum
       total number of request parameters (including uploaded files) obtained


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to