Tomcat is a popular, lightweight Java servlet container. It is often installed along with administrative applications. Under Debian and Ubuntu, these are part of a separate package, tomcat6-admin (in the case of Tomcat 6). Although the admin application is no longer available, both a manager and host-manager application is provided. When deploying Tomcat in production, the best risk mitigation strategy is to remove them (or not install them in the first place). However, if you choose to, or need to keep these services then additional controls are required. Where and how?
The Admin Apps
First a little about these applications. The Manager application lets you install new web applications (on a non-persistent basis), and also allows you to stop, reload, remove, or undeploy a web application. If you stop an application it becomes unavailable until it is restarted. If a user attempts to access an application that has been stopped, an error message, such as 503 – This application is not currently available, will be returned. Note, removing a web application only removes it only from the currently running instance of Tomcat — if it was started from the configuration files, it will reappear the next time Tomcat is restarted, i.e., the web application content is not deleted from disk.
The host-manager application controls virtual hosts, and how they are mapped to contexts. If you have several domain names mapped to the same IP address, Tomcat can direct a request for each of those names to different contexts, for example.
How should access to these applications be restricted? Enter the Valve element, which as described by the Tomcat documentation is “a component that will be inserted into the request processing pipeline for the associated Catalina container.” For our purposes, that container can be a context (e.g. the manager application) or a host (e.g. the host-manager application). A simple technique for restricting access is by IP address. For this purpose the Java class for the particular valve of interest is org.apache.catalina.valves.RemoteAddrValve aka the remote address filter. The XML syntax for this filter makes use of allow and/or deny statements The Valve documentation makes two things apparent about this filter:
- These statements are a comma-separated list of regular expression patterns to which the remote client’s IP address is compared
- The syntax for regular expressions is different than that for ‘standard’ wildcard matching; Tomcat uses the java.util.regex package.
If you did a search, you are likely to find rather simple examples like:
<Valve className=”org.apache.catalina.valves.RemoteAddrValve” allow=”127.0.0.1″/>
<Valve className=”org.apache.catalina.valves.RemoteAddrValve” allow=”172.128.101.*”/>
These imply standard wildcard matching, but we just read above that this is not the case. All regex meta-characters should be properly escaped. The examples above would work, but danger lurks. For example:
<Valve className=”org.apache.catalina.valves.RemoteAddrValve” allow=”10.10.10.*”/>
…would actually match 10.10.10.0/24, 10.10.10.101.0/24, 10.10.10.102.0/24, etc.
The difference is that the final dot (‘.’) matches either a dot or a digit, and either would be valid in an IP address in which the last provided octet has only two digits.
Thus, the proper way to do this is:
<Valve className=”org.apache.catalina.valves.RemoteAddrValve” allow=”10\.10\.10\..*”/>
Of course more sophisticated possibilities exist. For example:
<Valve className=”org.apache.catalina.valves.RemoteAddrValve” allow=”10\.10\.1\..*”/>
…would match 10.10.11/24 and 10.10.12/24.
The CIS Benchmark for Tomcat correctly highlights the fact that these are regular expressions, and not just wildcards.
By now you’re asking, where I we actually put these statements? Each of these applications has an XML context descriptor. The Tomcat documentation will define their location as:
For Tomcat 6 on Debian and its derivatives, e.g. Ubuntu, $CATALINA_BASE is /var/lib/tomcat6. But Debian nicely places configuration files under /etc, so /var/lib/tomcat6/conf is really just a symlink to /etc/tomcat6. All of that to say that the context descriptors for the admin applications are located in:
The default context descriptor will look like:
<Context path="/manager" docBase="/usr/share/tomcat6-admin/manager" antiResourceLocking="false" privileged="true" />
To add the valve, we need to modify the XML slightly.
<Context path="/manager" docBase="/usr/share/tomcat6-admin/manager" antiResourceLocking="false" privileged="true"> <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="10\.10\.10\..*"/> </Context>
Now restart Tomcat and test!
There are of course a great many good recommendations for Tomcat security in the aforementioned CIS Benchmark for Tomcat 5.5/6 and on the OWASP Wiki page for securing Tomcat.