Skip to content
Advertisement

Docker Tomcat 9.0.45 Stateless Container Hardening – Change ServerInfo.properties

As one of the hardening tasks defined for Tomcat, I’m supposed to change the output of $CATALINA_HOME/bin/version.sh to output bogus values.

This seemed pretty straight-forward from what I could find. All of the articles essentially pointed towards: extract ServerInfo.properties from catalina.jar, modify it, recommit it, and restart Tomcat.

In the stateless container world though, I have to extract it, modify it, recommit it, START tomcat. If I restart the container after tomcat is started, the container dies. Here are the steps I tried in my container entrypoint shell script:

jar -xf /opt/tomcat/lib/catalina.jar org/apache/catalina/util/ServerInfo.properties
sed -i 's@server.info=.*@server.info=Server@' /opt/tomcat/org/apache/catalina/util/ServerInfo.properties
sed -i 's@server.number=.*@server.info=0.0@' /opt/tomcat/org/apache/catalina/util/ServerInfo.properties
jar -uf /opt/tomcat/lib/catalina.jar org/apache/catalina/util/ServerInfo.properties

However, in 9.0.45, the recommit back to catalina.jar throws an error:

jar: Package org.apache.catalina.ssi missing from ModulePackages class file attribute

Investigating this, I found this article: jar: Package org.apache.catalina.ssi missing from ModulePackages class file attribute

…which essentially said it’s a bug in newer versions of tomcat and the guy who got around it used 7zip instead of jar. So I modified my code with the following:

mkdir -p /opt/tomcat/test
pushd /opt/tomcat/test
7z x -y /opt/tomcat/lib/catalina.jar:org/apache/catalina/util/ServerInfo.properties
sed -i 's@server.info=.*@server.info=Server@' /opt/tomcat/test/ServerInfo.properties
sed -i 's@server.number=.*@server.info=0.0@' /opt/tomcat/test/ServerInfo.properties
7z u /opt/tomcat/lib/catalina.jar:org/apache/catalina/util/ServerInfo.properties /opt/tomcat/test/ServerInfo.properties
popd

…while this did work in-so-far as I can tell (the ServerInfo.properties file in the backup location (test) did successfully get modified and I received a success indicator from 7zip in the container console log output for the recommit), after tomcat starts and I run version.sh, it still reports the actual verison.

To reiterate, these changes are being applied before tomcat is ever started so even though all of the documentation says to restart tomcat after-the-change, I’m expecting that I shouldn’t have to restart tomcat (again, since this operation kills the container and wipes any interactive container changes (stateless)).

EDIT 1: In an effort to confirm, after the container is started, I’ve exec’d into the container to verify that the entrypoint script was successful. I manually extracted the file out of catalina.jar and verified that the operations did appear to be successful because the interactively-extracted ServerInfo.properties from catalina.jar does reflect the changes (so the process appears to have worked) but running $CATALINA_HOME/bin/version.sh still shows the actual version…

Advertisement

Answer

There is another option which is much easier and works just fine.

Alternatively, the version number can be changed by creating the file CATALINA_BASE/lib/org/apache/catalina/util/ServerInfo.properties with content as follows…
https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#web.xml

You don’t need to replace anything in catalina.jar
Just create this extra config file as follows, that is enough.

mkdir -p "${CATALINA_HOME}/lib/org/apache/catalina/util"
echo "server.info=X" > "${CATALINA_HOME}/lib/org/apache/catalina/util/ServerInfo.properties"

## proceed with tomcat start...

Bonus
Remove server info from HTTP headers in server responses (also check this).

## turn off server info and stacktraces on error pages
file="${CATALINA_HOME}"/conf/server.xml
xmlstarlet edit -L 
    --delete "//Connector[starts-with(@protocol, 'HTTP')]/@server" 
    --insert "//Connector[starts-with(@protocol, 'HTTP')]" -t attr -n "server" -v "X" 
    --delete "//Valve[@className='org.apache.catalina.valves.ErrorReportValve']" 
    --subnode "/Server/Service[@name='Catalina']/Engine[@name='Catalina']/Host[@name='localhost']" -t elem -n "Valve" 
    --insert "/Server/Service[@name='Catalina']/Engine[@name='Catalina']/Host[@name='localhost']/Valve[not(@className)]" -t attr -n "className" -v "org.apache.catalina.valves.ErrorReportValve" 
    --insert "//Valve[@className='org.apache.catalina.valves.ErrorReportValve']" -t attr -n "showReport" -v "false" 
    --insert "//Valve[@className='org.apache.catalina.valves.ErrorReportValve']" -t attr -n "showServerInfo" -v "false" 
${file}
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement