Harden Tomcat
This article describes how to harden your Tomcat installation. The examples applies to Apache Tomcat 8.x.
Step-by-step instructions
Tomcat version 9.0.76 or higher is required to support the Rate limit filter. The filter can be used for older Prime/Identity Manager versions as well if Tomcat is updated to a supported version.
To prevent "Denial of Service" (DoS) attacks, a "Rate limit filter" can be added to web.xml in the Tomcat installation.
In Smart ID Docker containers it will be added automatically.
The filter can be added to web.xml for each application if adjusting the settings individually is needed, instead of having a global setting valid for all applications. However, it is easier to maintain in one location.
Configure the filter in Tomcat/conf/web.xml. See an example below:
Example: Rate limit filter
<!-- Filter to prevent Denial of Service (DoS) and Brute Force attacks by limiting
the number of requests that are allowed from a single IP address
during a certain time span (time bucket) -->
<filter>
<filter-name>RateLimitFilter global</filter-name>
<filter-class>org.apache.catalina.filters.RateLimitFilter</filter-class>
<init-param>
<!-- The number of requests that are allowed in a time bucket. Default is 300. -->
<param-name>bucketRequests</param-name>
<param-value>200</param-value>
</init-param>
<init-param>
<!-- The number of seconds in a time bucket. Default is 60. -->
<param-name>bucketDuration</param-name>
<param-value>60</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>RateLimitFilter global</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
Go to the
$tomcat/conf
folderModify server.xml by using a text editor.
Add the following to
Connector port
:CODEServer =" "
Example:
Example: Remove server banner
CODE<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000" Server =" " redirectPort="8443" />
To enable TLS/SSL, add a connector for port 443 to the Tomcat configuration:
Go to the
$tomcat/conf
folderModify server.xml by using a text editor.
Add the following content:
CODE<Connector port="443" protocol="org.apache.coyote.http11.Http11Protocol" Server=" " SSLEnabled="true" maxPostSize="-1" maxThreads="800" minSpareThreads="80" maxSpareThreads="160" disableUploadTimeout="true" scheme="https" secure="true" clientAuth="false" keystoreFile="/opt/tomcat/cert/myssl.p12" keystorePass="<secretpassword>" keystoreType="PKCS12" truststoreFile="/opt/tomcat/cert/castore.jks" truststorePass="<secretpassword>" truststoreType="JKS" sslProtocol="TLS" sslEnabledProtocols="TLSv1.2" useServerCipherSuitesOrder="true" ciphers="TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" />
For more information, see https://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html.
Even if you have an http connector, for example in port 8080, it will redirect to the configured ssl port. To enforce HTTPS, do the following:
Go to the $tomcat/conf folder
Modify web.xml with a text editor.
Add the following before the
</web-app>
syntax:CODE<security-constraint> <web-resource-collection> <web-resource-name>Protected Context</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>
It is possible to steal or manipulate web application session and cookies without having a secure cookie. Here "secure
" is a flag which is injected in the response header.
Add this line in the
session-config
section of the web.xml file:CODE<cookie-config> <http-only>true</http-only> <secure>true</secure> </cookie-config>
This is valid for Linux- and Unix-like operating systems.
To lower the impact of a potential attack, it is recommended to run Tomcat with a non-privileged user. Follow these steps to add a non-privileged user and run Tomcat with that user:
Create a group called
tomcat
.Add a user called
tomcat
to thetomcat
group, with the following attributes:Set the home directory to /opt/tomcat. This directory is where Tomcat is installed.
Set the shell to /bin/nologin (so that nobody can log into the account).
Start Tomcat as the new
tomcat
user.Linux example: add tomcat group and user
CODE# Preparation sudo groupadd tomcat sudo useradd -M -s /bin/nologin -g tomcat -d /opt/tomcat tomcat sudo chgrp -R tomcat /opt/tomcat sudo chmod -R g+r conf sudo chmod g+x conf sudo chown -R tomcat webapps/ work/ temp/ logs/ cert/ # Startup as tomcat user sudo su -c /opt/tomcat/bin/startup.sh - tomcat
By default, Tomcat comes with the following web applications, which may be required in a production environment. You can delete them to keep it clean and avoid any known security risk with Tomcat default application.
ROOT
– Default welcome pageDocs
– Tomcat documentationExamples
– JSP and servlets for demonstrationManager, host-manager
– Tomcat administration
They are available under the $tomcat/webapps
folder.
By default, Tomcat is configured to be shutdown via port 8005. Tomcat can then be shut down by opening telnet to IP:port and issuing the SHUTDOWN command.
It’s recommended to change the Tomcat shutdown port and default command to something unpredictable.
Modify the following in server.xml:
CODE<Server port="8005" shutdown="<complicatedpassword>">
Or disable the shutdown port completely:
CODE<Server port="-1" shutdown="SHUTDOWN">
If you have the default pages for not found (404), forbidden (403), and server error (5xx), this will expose version details.
To mitigate this:
Create a general error page:
Go to the
$tomcat/webapps/$application.
Create an error.jsp file using a text editor.
Example
CODE<html> <head> <title>Error Page</title> </head> <body> That's an error! </body> </html>
Configure web.xml to redirect to the general error page.
Go to the $tomcat/conf folder.
Add the following in the web.xml file before the
</web-app>
syntax:CODE<error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>403</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error.jsp</location> </error-page>
You can also do the same for
java.lang.Exception
. This will help in not exposing the Tomcat version information if any such error happens. Add the following in web.xml and restart the tomcat server:CODE<error-page> <exception-type>java.lang.Exception</exception-type> <location>/error.jsp</location> </error-page>
If you don't want Identity Manager Admin or Identity Manager Tenant to be accessible over the internet, this is an example of how you can restrict access per application in Tomcat.
Modify $tomcat/webapps/$application/META-INF/context.xml
This will allow access from IPV4 localhost, IPV6 localhost, any IP that begins with 10 and also from the public IP of the Nexus Stockholm Office.CODE<context> <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|10\.\d+\.\d+\.\d+|83\.\241\.\229\.\132|::1|0:0:0:0:0:0:0:1" /> </context>
Restart Tomcat for changes to apply.
If you want to hide the stack trace thrown by Tomcat (Application Server) when something goes wrong or there is an error in some configuration file then this is an example of how you can restrict display of error stack trace.
To hide the tomcat stack trace add the following lines to the host section of your server.xml file under <apche-tomcat>\conf where you should already have the AccessLogValve:
Modify $tomcat/conf /server.xml
CODE<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false"/>
Disabling both
showServerInfo
andshowReport
will now only return the HTTP status code.Restart Tomcat for changes to apply.