On Thu, Jan 16, 2025 at 5:42 PM Mark Thomas <ma...@apache.org> wrote: > > On 16/01/2025 16:38, ma...@apache.org wrote: > > This is an automated email from the ASF dual-hosted git repository. > > > > markt pushed a commit to branch 9.0.x > > in repository https://gitbox.apache.org/repos/asf/tomcat.git > > > > > > The following commit(s) were added to refs/heads/9.0.x by this push: > > new 427732ef8e Automate protection for CVE-2024-56337 > > 427732ef8e is described below > > > > commit 427732ef8ee7f707a32734a13a926a2d070b8ba9 > > Author: Mark Thomas <ma...@apache.org> > > AuthorDate: Thu Jan 16 16:37:06 2025 +0000 > > > > Automate protection for CVE-2024-56337 > > > > If there is a potentially vulnerable web application (Java < 21, > > WebResourceSet configured for read/write, case-insensitive file system) > > ensure that the JVM behaves as if sun.io.useCanonCaches is false. If > > that cannot be ensured, prevent the potentially vulnerable web > > applications from starting. > > I looked at various approaches for this and settled on this one after a > few experiements. I wanted to give folks a little time for feedback > before porting it to 10.1.x and 11.0.x. I won't port it to main since > that requires Java 21 where the problematic JVM setting doesn't exist.
Ok, it works. Rémy > Mark > > > --- > > bin/catalina.bat | 7 +++ > > bin/catalina.sh | 7 +++ > > .../catalina/webresources/DirResourceSet.java | 29 +++++++++ > > .../catalina/webresources/LocalStrings.properties | 2 + > > .../org/apache/tomcat/util/compat/Jre21Compat.java | 14 +++++ > > java/org/apache/tomcat/util/compat/JreCompat.java | 69 > > +++++++++++++++++++++- > > .../tomcat/util/compat/LocalStrings.properties | 3 + > > webapps/docs/changelog.xml | 9 +++ > > 8 files changed, 139 insertions(+), 1 deletion(-) > > > > diff --git a/bin/catalina.bat b/bin/catalina.bat > > index 05704d6115..9fc3da0369 100755 > > --- a/bin/catalina.bat > > +++ b/bin/catalina.bat > > @@ -219,6 +219,13 @@ rem Register custom URL handlers > > rem Do this here so custom URL handles (specifically 'war:...') can be > > used in the security policy > > set "JAVA_OPTS=%JAVA_OPTS% > > -Djava.protocol.handler.pkgs=org.apache.catalina.webresources" > > > > +rem Disable the global canonical file name cache to protect against > > CVE-2024-56337 > > +rem Note: The cache is disabled by default in Java 12 to 20 inclusive > > +rem The cache is removed in Java 21 onwards > > +rem Need to set this here as java.io.FileSystem caches this in a static > > field during class > > +rem initialisation so it needs to be set before any file system access > > +set "JAVA_OPTS=%JAVA_OPTS% -Dsun.io.useCanonCaches=false" > > + > > rem Check for the deprecated LOGGING_CONFIG > > rem Only use it if CATALINA_LOGGING_CONFIG is not set and LOGGING_CONFIG > > starts with "-D..." > > if not "%LOGGING_CONFIG:~0,2%"=="-D" goto noLoggingDeprecation > > diff --git a/bin/catalina.sh b/bin/catalina.sh > > index 3a2ffdafa0..8d07001214 100755 > > --- a/bin/catalina.sh > > +++ b/bin/catalina.sh > > @@ -268,6 +268,13 @@ JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS" > > # Do this here so custom URL handles (specifically 'war:...') can be used > > in the security policy > > JAVA_OPTS="$JAVA_OPTS > > -Djava.protocol.handler.pkgs=org.apache.catalina.webresources" > > > > +# Disable the global canonical file name cache to protect against > > CVE-2024-56337 > > +# Note: The cache is disabled by default in Java 12 to 20 inclusive > > +# The cache is removed in Java 21 onwards > > +# Need to set this here as java.io.FileSystem caches this in a static > > field during class > > +# initialisation so it needs to be set before any file system access > > +JAVA_OPTS="$JAVA_OPTS -Dsun.io.useCanonCaches=false" > > + > > # Check for the deprecated LOGGING_CONFIG > > # Only use it if CATALINA_LOGGING_CONFIG is not set and LOGGING_CONFIG > > starts with "-D..." > > if [ -z "$CATALINA_LOGGING_CONFIG" ]; then > > diff --git a/java/org/apache/catalina/webresources/DirResourceSet.java > > b/java/org/apache/catalina/webresources/DirResourceSet.java > > index 512adf8b8a..4f39e87378 100644 > > --- a/java/org/apache/catalina/webresources/DirResourceSet.java > > +++ b/java/org/apache/catalina/webresources/DirResourceSet.java > > @@ -36,6 +36,7 @@ import > > org.apache.catalina.WebResourceRoot.ResourceSetType; > > import org.apache.catalina.util.ResourceSet; > > import org.apache.juli.logging.Log; > > import org.apache.juli.logging.LogFactory; > > +import org.apache.tomcat.util.compat.JreCompat; > > import org.apache.tomcat.util.http.RequestUtil; > > > > /** > > @@ -335,6 +336,34 @@ public class DirResourceSet extends > > AbstractFileResourceSet implements WebResour > > } > > } > > } > > + // Check for exposure to CVE-2024-56337 > > + if (caseSensitive) { > > + // CVE-2024-56337 (nor CVE-2024-50379) is not exploitable on a > > case sensitive file system > > + return; > > + } > > + if (isReadOnly()) { > > + // CVE-2024-56337 (nor CVE-2024-50379) is not exploitable on a > > read-only ResourceSet > > + return; > > + } > > + if (JreCompat.getInstance().isCanonCachesDisabled()) { > > + // CVE-2024-56337 (nor CVE-2024-50379) is not exploitable if > > the canonical file name cache is disabled > > + return; > > + } > > + // This ResourceSet may be exposed to CVE-2024-56337. > > + if (JreCompat.getInstance().disableCanonCaches()) { > > + /* > > + * The canonical file name cache was enabled and is now > > disabled. > > + */ > > + log.warn(sm.getString("dirResourceSet.canonCaches.disabled", > > getFileBase(), > > + getRoot().getContext().getName())); > > + } else { > > + /* > > + * The canonical file name cache could not be disabled (or > > Tomcat cannot confirm it has been disabled). This > > + * ResourceSet may be exposed to CVE-2024-56337. > > + */ > > + throw new > > IllegalStateException(sm.getString("dirResourceSet.canonCaches.enabled", > > getFileBase(), > > + getRoot().getContext().getName())); > > + } > > } > > > > > > diff --git a/java/org/apache/catalina/webresources/LocalStrings.properties > > b/java/org/apache/catalina/webresources/LocalStrings.properties > > index 20bcdf5330..2590428e09 100644 > > --- a/java/org/apache/catalina/webresources/LocalStrings.properties > > +++ b/java/org/apache/catalina/webresources/LocalStrings.properties > > @@ -36,6 +36,8 @@ cachedResource.invalidURL=Unable to create an instance of > > CachedResourceURLStrea > > > > classpathUrlStreamHandler.notFound=Unable to load the resource [{0}] > > using the thread context class loader or the current class''s class loader > > > > +dirResourceSet.canonCaches.disabled=Disabled the global canonical file > > name cache to protect against CVE-2024-56337 when starting the > > WebResourceSet at [{0}] which is part of the web application [{1}] > > +dirResourceSet.canonCaches.enabled=Unable to disable the global canonical > > file name cache or confirm that it is disabled when starting the > > WebResourceSet at [{0}] which is part of the web application [{1}]. The > > WebResourceSet may be exposed to CVE-2024-56337. > > dirResourceSet.isCaseSensitive.fail=Error trying to determine if file > > system at [{0}] is case sensitive so assuming it is not case sensitive > > dirResourceSet.manifestFail=Failed to read manifest from [{0}] > > dirResourceSet.notDirectory=The directory specified by base and internal > > path [{0}]{1}[{2}] does not exist. > > diff --git a/java/org/apache/tomcat/util/compat/Jre21Compat.java > > b/java/org/apache/tomcat/util/compat/Jre21Compat.java > > index c534ea4e2d..ee01f3e28e 100644 > > --- a/java/org/apache/tomcat/util/compat/Jre21Compat.java > > +++ b/java/org/apache/tomcat/util/compat/Jre21Compat.java > > @@ -104,4 +104,18 @@ public class Jre21Compat extends Jre19Compat { > > throw new CompletionException(e); > > } > > } > > + > > + > > + @Override > > + public boolean isCanonCachesDisabled() { > > + // The cache has been removed in Java 21 > > + return true; > > + } > > + > > + > > + @Override > > + public boolean disableCanonCaches() { > > + // The cache has been removed in Java 21 > > + return true; > > + } > > } > > diff --git a/java/org/apache/tomcat/util/compat/JreCompat.java > > b/java/org/apache/tomcat/util/compat/JreCompat.java > > index 66b11684c7..135b7bc21c 100644 > > --- a/java/org/apache/tomcat/util/compat/JreCompat.java > > +++ b/java/org/apache/tomcat/util/compat/JreCompat.java > > @@ -37,6 +37,8 @@ import javax.net.ssl.SSLEngine; > > import javax.net.ssl.SSLParameters; > > import javax.security.auth.Subject; > > > > +import org.apache.juli.logging.Log; > > +import org.apache.juli.logging.LogFactory; > > import org.apache.tomcat.util.res.StringManager; > > > > /** > > @@ -45,6 +47,9 @@ import org.apache.tomcat.util.res.StringManager; > > */ > > public class JreCompat { > > > > + private static final Log log = LogFactory.getLog(Jre21Compat.class); > > + private static final StringManager sm = > > StringManager.getManager(JreCompat.class); > > + > > private static final int RUNTIME_MAJOR_VERSION = 8; > > > > private static final JreCompat instance; > > @@ -55,8 +60,8 @@ public class JreCompat { > > private static final boolean jre19Available; > > private static final boolean jre21Available; > > private static final boolean jre22Available; > > - private static final StringManager sm = > > StringManager.getManager(JreCompat.class); > > > > + private static final Field useCanonCachesField; > > protected static final Method setApplicationProtocolsMethod; > > protected static final Method getApplicationProtocolMethod; > > > > @@ -119,6 +124,21 @@ public class JreCompat { > > } > > jre11Available = instance.jarFileRuntimeMajorVersion() >= 11; > > > > + Field f1 = null; > > + try { > > + Class<?> clazz = Class.forName("java.io.FileSystem"); > > + f1 = clazz.getDeclaredField("useCanonCaches"); > > + f1.setAccessible(true); > > + } catch (ReflectiveOperationException | IllegalArgumentException > > e) { > > + /* > > + * Log at debug level as this will only be an issue if the > > field needs to be accessed and most > > + * configurations will not need to do so. Appropriate warnings > > will be logged if an attempt is made to use > > + * the field when it could not be found/accessed. > > + */ > > + log.debug(sm.getString("jreCompat.useCanonCaches.init"), e); > > + } > > + useCanonCachesField = f1; > > + > > Method m1 = null; > > Method m2 = null; > > try { > > @@ -482,4 +502,51 @@ public class JreCompat { > > throw new CompletionException(e); > > } > > } > > + > > + > > + /* > > + * The behaviour of the canonical file cache varies by Java version. > > + * > > + * The cache was removed in Java 21 so these methods and the > > associated code can be removed once the minimum Java > > + * version is 21. > > + * > > + * For 12 <= Java <= 20, the cache was present but disabled by > > default. Since the user may have changed the default > > + * Tomcat has to assume the cache is enabled unless proven otherwise. > > + * > > + * For Java < 12, the cache was enabled by default. Tomcat assumes the > > cache is enabled unless proven otherwise. > > + */ > > + public boolean isCanonCachesDisabled() { > > + if (useCanonCachesField == null) { > > + // No need to log a warning. The warning will be logged when > > trying to disable the cache. > > + return false; > > + } > > + boolean result = false; > > + try { > > + result = !((Boolean) > > useCanonCachesField.get(null)).booleanValue(); > > + } catch (ReflectiveOperationException e) { > > + // No need to log a warning. The warning will be logged when > > trying to disable the cache. > > + } > > + return result; > > + } > > + > > + > > + /** > > + * Disable the global canonical file cache. > > + * > > + * @return {@code true} if the global canonical file cache was already > > disabled prior to this call or was disabled > > + * as a result of this call, otherwise {@code false} > > + */ > > + public boolean disableCanonCaches() { > > + if (useCanonCachesField == null) { > > + log.warn(sm.getString("jreCompat.useCanonCaches.none")); > > + return false; > > + } > > + try { > > + useCanonCachesField.set(null, Boolean.TRUE); > > + } catch (ReflectiveOperationException | IllegalArgumentException > > e) { > > + log.warn(sm.getString("jreCompat.useCanonCaches.failed"), e); > > + return false; > > + } > > + return true; > > + } > > } > > diff --git a/java/org/apache/tomcat/util/compat/LocalStrings.properties > > b/java/org/apache/tomcat/util/compat/LocalStrings.properties > > index ad858297e9..4b33b7a4aa 100644 > > --- a/java/org/apache/tomcat/util/compat/LocalStrings.properties > > +++ b/java/org/apache/tomcat/util/compat/LocalStrings.properties > > @@ -37,3 +37,6 @@ jreCompat.noApplicationProtocol=Java Runtime does not > > support SSLEngine.getAppli > > jreCompat.noApplicationProtocols=Java Runtime does not support > > SSLParameters.setApplicationProtocols(). You must use Java 9 to use this > > feature. > > jreCompat.noUnixDomainSocket=Java Runtime does not support Unix domain > > sockets. You must use Java 16 or later to use this feature. > > jreCompat.noVirtualThreads=Java Runtime does not support virtual threads. > > You must use Java 21 or later to use this feature. > > +jreCompat.useCanonCaches.failed=Failed to set the > > java.io.FileSystem.useCanonCaches static field > > +jreCompat.useCanonCaches.init=Unable to create a reference to the > > java.io.FileSystem.useCanonCaches static field > > +jreCompat.useCanonCaches.none=No reference to the > > java.io.FileSystem.useCanonCaches static field available. Enable debug > > logging for more information. > > diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml > > index 4c54b39903..1861714fcc 100644 > > --- a/webapps/docs/changelog.xml > > +++ b/webapps/docs/changelog.xml > > @@ -140,6 +140,15 @@ > > Improve checks for <code>WEB-INF</code> and <code>META-INF</code> > > in > > the WebDAV servlet. Based on a patch submitted by Chenjp. (remm) > > </fix> > > + <add> > > + Add a check to ensure that, if one or more web applications are > > + potentially vulnerable to CVE-2024-56337, the JVM has been > > configured to > > + protect against the vulnerability and to configure the JVM > > correctly if > > + not. Where one or more web applications are potentially vulnerable > > to > > + CVE-2004-56337 and the JVM cannot be correctly configured or it > > cannot > > + be confirmed that the JVM has been correctly configured, prevent > > the > > + impacted web applications from starting. (markt) > > + </add> > > </changelog> > > </subsection> > > <subsection name="Coyote"> > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > > For additional commands, e-mail: dev-h...@tomcat.apache.org > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail: dev-h...@tomcat.apache.org > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org