Monday, May 23, 2011

Installing Apache Tomcat under Linux

After a security outage I experienced recently with JBOSS I decided to move my webapp to Apache Tomcat. The incident was an exploit of zecmd.war that needs to be removed from $JBOSS_HOME/server/default/deploy/management/ directory. Once again this reminds me of the thinning that needs to take place before JBOSS is taken to production. A good guide for thinning JBOSS can be found here.

Nonetheless, the decision was taken: we were moving to Apache Tomcat version 7. The installation we performed under Linux is not a difficult one; however, certain steps need to take place so as to address reliability/security. Let’s go through the installation step by step. First, we need to download and install java, as well as tomcat. Tomcat needs java version 1.6 in order to function and so JDK 1.6 can be found here.
After java is in place, we may download Tomcat 7 and this can be found here.
After downloading apache-tomcat-7.0.14.tar.gz (current stable version as of this writing), as root, I did the following:
Create tomcat user and group:

$>groupadd tomcat
$>useradd tomcat –m –g tomcat

Move apache-tomcat-7.0.14.tar.gz  under /opt. Then unpack the *.tar.gz and remove it so as to gain space. Finally change ownership of the newly created directory to tomcat user:

$>mv apache-tomcat-7.0.14.tar.gz /opt
$>tar –xvf apache-tomcat-7.0.14.tar.gz
$>rm apache-tomcat-7.0.14.tar.gz
$>chown –R tomcat:tomcat apache-tomcat-7.0.14

What we have now is a brand new installation of Apache Tomcat owned by tomcat OS user. Directory /opt/ apache-tomcat-7.0.14 is our CATALINA_HOME. Next we need to fix up a bit tomcat user with the right environment variables, like CATALINA_HOME mentioned above. Go to the user’s home directory and edit .profile file. Add the following parameters:

JAVA_HOME=/usr/java/jdk1.6.0_25  
export JAVA_HOME  
PATH=$JAVA_HOME/bin:$PATH  
export PATH  
CATALINA_BASE=/opt/ apache-tomcat-7.0.14
export CATALINA_BASE
CATALINA_HOME=/opt/ apache-tomcat-7.0.14
export CATALINA_HOME
CATALINA_OPTS=”$CATALINA_OPTS -Xms128m -Xmx512m -server”

JAVA_HOME is needed to point out to the directory that java is installed. So,\ as to be sure, $JAVA_HOME/bin/java file should exist. Otherwise, you will get an error in Tomcat’s log directory stating that $JAVA_HOME/bin/java file is invalid. Also, if java can be found under /usr/bin do not use /usr as CATALINA_HOME, but better the actual directory where java was installed (in my case =/usr/java/jdk1.6.0_25 ).  After all, /usr/bin/java is a symbolic link pointing to the actual java binary.

CATALINA_BASE and CATALINA_HOME is the directory where Tomcat is installed. CATALINA_BASE may be left out, but CATALINA_HOME is absolutely mandatory.

CATALINA_OPTS dictates, among others, the heap parameters for starting Tomcat, as well as indicate that we need to start it as a server.
 
Another good idea is to run Tomcat as a service in Linux, by placing the appropriate tomcat file under /etc/init.d. Mine looks like this:

JAVA_HOME=/usr/java/jdk1.6.0_25  
export JAVA_HOME  
PATH=$JAVA_HOME/bin:$PATH  
export PATH  
CATALINA_BASE=/opt/ apache-tomcat-7.0.14
export CATALINA_BASE
CATALINA_HOME=/opt/ apache-tomcat-7.0.14
export CATALINA_HOME
CATALINA_OPTS=”$CATALINA_OPTS -Xms128m -Xmx512m -server”
case $1 in  
start)  
bash $CATALINA_HOME/bin/startup.sh  
;;   
stop)     
bash $CATALINA_HOME/bin/shutdown.sh  
;;   
restart)  
bash $CATALINA_HOME/bin/shutdown.sh  
pid=$(ps -ef | grep tomcat | grep java | grep -v grep | grep -v stop | awk '{print $2}')
while [[ "$pid" != "" ]]
do
sleep 2
echo "shutting down app server.."
pid=$(ps -ef | grep tomcat | grep java | grep -v grep | grep -v stop | awk '{print $2}')
done
bash $CATALINA_HOME/bin/startup.sh  
;;   
esac      
exit 0 

We may then add appropriate permissions to this file. Do the following so as to fix this:

$>chmod 755 /etc/init.d/tomcat

We are now ready to start Tomcat as a service under tomcat user, like this:

$>su – tomcat
$>service tomcat start

But beware! Let us first secure our installation. Take the following steps:

1. Remove all files and folders under $CATALINA_HOME/webapps, $CATALINA_HOME/server/webapps, as well as some other files not necessary to common production:

$>rm –rf $CATALINA_HOME/webapps
$>rm $CATALINA_HOME/server/webapps

   
2. Make sure $CATALINA_HOME/conf/web.xml file has an entry called listings set to
false. By default it is, but you may edit the file just to make sure:

<init-param>
     <param-name>listings</param-name>
     <param-value>false</param-value> 
</init-param>


In the same file, make sure that the following entry exists as follows:
       
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/manos.jsp</location>
</error-page>


As you may have guessed, manos.jsp does not exist, so in case of a Java Exception the user will receive a blank page instead of the stacktrace, which can reveal vulnerability in your app. Please note however that in my app I have configured my own 500 and 404 error pages.

3. So as to reveal as little as possible to a potential attacker in HTTP headers, you may edit $CATALINA_HOME/conf/server.xml file and add the server=”Something” entry in all Connectors. It will look like this:

<Connector port="8080" server="Something" />

4. Change the shutdown command in $CATALINA_HOME/conf/server.xml to something other than the default SHUTDOWN. Also, make sure that a proper set up of iptables hides port 8005 from the outside world.
        
<Server port="8005" shutdown="LukeSkywalker">
 
5.  Make certain directory/file restrictions harder, as follows:

$>chmod 700 $CATALINA_HOME/conf
$>chmod 700 $CATALINA_HOME/conf/*
$>chmod 700 $CATALINA_HOME/temp
 
And after all this set up, you are pretty much done!

Some additional steps I did was to configure all Connector entries in $CATALINA_HOME/conf/server.xml to use UTF8 by placing entry URIEncoding="UTF-8", place connector/j library for mysql under $CATALINA_HOME/lib directory and editing $CATALINA_HOME/conf/context.xml to add the mysql datastore (the latter might not be a best practice, since this resource is globally available to all apps running under Tomcat - an alternative approach would be to place it under $CATALINA_HOME/conf/Catalina/localhost/ROOT.xml, assuming your app is called ROOT).

1 comment:

  1. Another good resource for Tomcat Security is Google. A project that can be found under http://securetomcat.googlecode.com.

    I twicked a bit the securetomcat.sh script to be able to run it under Ubuntu 10.04.

    To be extact I changed line

    "`echo $COMMAND`" =~ "-Dcatalina.home=(.*) -"

    to

    $COMMAND =~ "-Dcatalina.home="(.*)" -"

    so that the regex could match.

    ReplyDelete