Shared JVM Tomcat Security Notes
Shared JVM accounts running within the Tomcat
Servlet container present a cost effective solution for a Java hosting requirement.
However, following a security audit carried out by ourselves we propose that they
pose a fundamental security risk which is incompatible with a secure shared hosting
environment. In light of these findings we no longer offer shared private JVM accounts.
Please note that we have moved all existing shared JVM accounts to individual Tomcat instances.
Filesystem privileges and autodeployment
A central aspect of Servlet technology is to use .war files to deploy
applications (defined within the Servlet specification).
This deployment process is reliant on Tomcat (or equivalent Servlet container) recognising
that a .war file has been added to a deployment directory. To do this Tomcat needs to run
as a user which has at minimum read access to the deployment directory, and if expand is
set to true write access. As user's code has the same privileges as Tomcat this means that each
user within a shared JVM environment has at minimum read access to other user's web
directories and potentially write access. Extracting database passwords from other users web
application would be a relatively straight forward affair (Some web hosting companies even run
shared JVM instances as root!).
Privileged deployment
One of the strengths of using Tomcat as a Servlet container is the flexibility of the deployment
process. There are a number of methods to deploy applications within a Tomcat environment,
(such as the .war approach above), although focusing on using a .xml file highlights a
serious security issue. Under normal usage each web application is assigned its own classloader
which has been constructed so that the internal Tomcat classes cannot be seen. However,
to facilitate tools such as the 'manager' app and 'admin' app a 'privileged'
attribute can be set which gives the application access to Tomcat's internal classes. Theoretically,
this would give another user the privilege to stop / start / destroy another user's applications.
Non Chrooted Environment
'chroot' is a Unix system call which changes the root filesystem to a directory within the
normal filesystem which 'jails' a user within their own private filesystem. Using
this as a security mechanism is effective because it restricts their running processes (such as
Tomcat) from seeing sensitive areas of the filesytem (such as the database directory). This is
the technology we use this for our private JVMs. However, it is not possible to run a shared
Tomcat instance within a 'chrooted' environment as by its very nature it needs to see user's
home directories to deploy applications. This potentially gives other user's access to sensitive areas of
the filesystem which are insufficiently protected.
Performance
Ensuring a user does not use a disproportionate level of system resources on a Unix
platform is relatively simple to achieve. Monitoring the number of processes, allocated memory,
disk I/O and CPU usage of a user account and placing safety limits so that the health
of a system is not jeopardised and that no one user can 'crowd out' other users is a standard
facet of Unix administration. While this is achieveable at the 'inter' JVM level no viable
mechanism is available at the 'intra' (i.e. shared) JVM level. Taking an example, badly
written threaded code or code with memory leaks 1 could rapidly
overrun a shared JVM.
1. Contrary to popular belief it is possible for a Java application to 'leak' memory. Understanding
how the garbage collector works provides an insight into how this can occur. The garbage collector
works on the basis of reference counting, when it determines that no more references to an object exist
this object becomes eligible for garbage collection. However, it would be very simple within the collections
framework to have forgotten references hidden within a List, whose object graphs in turn will themselves
never be eligible for garbage collection.
Last updated: 15/08/2004
|