Apache Tomcat 8 - aber sicher
Der Apache Tomcat Webserver gehört seit 15 Jahren zu den am meisten eingesetzten Systemen im Bereich Java-Anwendungsserver. Java ist in letzter Zeit, vor allem auf dem Client oft durch Sicherheitslücken aufgefallen. Doch auch SSL ist im letzten Jahr durch Heartbleed und Poodle durch Implementierungs- und Konfigurationsfehler aufgefallen. In diesem Artikel will ich zeigen, wie man Apache Tomcat etwas sicherer machen kann, indem man ihn nicht einfach nur mit den Standardwerten einsetzt.
Da Apache Tomcat meist hinter einem vorgeschalteten Loadbalancer, wie Apache HTTPD oder Nginx, eingesetzt wird, meinen viele, damit genug für das Thema Absicherung getan zu haben. Doch weit gefehlt. Da Tomcat entweder embedded oder in der Cloud eingesetzt wird, spielt die angepasste Konfiguration eine immer größere Rolle.
Sicherheit von Anfang an
Das fängt schon bei der Installation an. Hier sollte man für Produktionssysteme immer überprüfen, ob die Installationsdatei seit der Erstellung unverändert ist. Das kann man einfach mit der md5-Hashsumme verifizieren über
md5sum -c apache-tomcat-8.0.15.zip.md5
Außerdem sollte man alle kritischen Komponenten (Tomcat, Java, JDBC-Treiber) in aktuellen Versionen einsetzen und auch regelmäßig aktualisieren.
Wer nicht immer die Bekanntgabe-Mailingliste, Sicherheitsbekanntgaben oder die Releasenotes des Tomcat-Projektes lesen möchte, um auf dem Laufenden zu sein, kann auch das CVE-Dependency-Check-Werkzeug [1] einsetzen. Dieses überprüft, ob für die Software in der NVD CVE Datenbank bekannte Sicherheitslücken existieren. Diese wird z.B. für den Tomcat wie folgt aufgerufen:
dependency-check.bat --app "Tomcat" --scan "C:\apache-tomcat-8.0.15\lib".
Tarnen, täuschen und Angriffsfläche minimieren gehören zum täglichen Rüstzeug.
Auch bei Apache Tomcat sollte man die Produktversion verschleiern. Das geht an drei Stellen: In der Datei CATALINA_BASE\conf\web.xml ist normalerweise das Senden des Server Headers aus Sicherheitsgründen immer deaktiviert.
<param-name>xpoweredBy</param-name> <param-value>false</param-value> <param-value>false</param-value>
In der gleichen Datei sollten Sie für den JSP-Compiler den Entwicklermodus deaktivieren.
<param-name>development</param-name> <param-value>false</param-value> <param-value>false</param-value>
In der Datei CATALINA_BASE/conf/server.xml sollten nur die wirklich verwendeten Ports aktiviert sein. Zusätzlich gilt es für jeden Port-Connector die Tomcat-Version zu überschreiben. Für den Standard-http-Port 8080 lautet der Eintrag
<Connector port="8080" ... server="Apache" />
Außerdem müssen auch in der Datei ServerInfo.properties die beiden Informationen server.info=Apache und server.number=0.0.0.0 überschrieben werden. Dazu wird diese Datei aus- und nach dem Ändern wieder ins Jar-Archiv eingepackt mit
jar xf catalina.jar org/apache/catalina/util/ServerInfo.properties jar uf catalina.jar org/apache/catalina/util/ServerInfo.properties jar uf catalina.jar org/apache/catalina/util/ServerInfo.properties
Überprüfen können Sie die beiden Änderungen nach einem Neustart des Tomcat-Servers mit version.[sh|bat] und dem Aufruf einer nicht vorhandenen Webseite z.B. localhost/abc.
Verschlüsselung, aber richtig
Wenn man eine SSL-Verschlüsselung in Tomcat benötigt, kann man sich zwischen zwei Möglichkeiten entscheiden. Entweder verwendet man OpenSSL mit der Apache Tomcat Native Library, die auf der Apache Portable Runtime (APR) basiert, oder verwendet die Standard Java Secure Socket Extension (JSSE). Zum Verwalten des Verschlüsselungszertifikats verwendet OpenSSL das PKCS12 (Public Key Cryptography Personal Information Exchange Syntax) Format und JSSE JKS (Java KeyStore).
Bei OpenSSL hat man eine etwas bessere Performance, man muss jedoch beim Update oft mehrere Komponenten aktualisieren, was etwas aufwändiger ist.
Wieder müssen wir in der Datei CATALINA_BASE/conf/server.xml den HTTPS-Connector, der standardmäßig unter Port 8443 läuft, anpassen. Für die Variante mit Apache Portable Runtime und OpenSSL lautet der Eintrag
protocol="org.apache.coyote.http11.Http11AprProtocol“
für JSSE
protocol="org.apache.coyote.http11.Http11NioProtocol“
Wenn man JSSE verwendet, muss man an der Java-Runtime folgende Änderungen vornehmen. Da Java standardmäßig nur mit schwachen Schlüsseln ausgeliefert wird, muss man von ORACLE die Unlimited Strength Jurisdiction Policy-Dateien herunterladen und damit die bestehenden ersetzen:
cp local_policy.jar US_export_policy.jar jre/lib/security.
Außerdem sollte man Schlüssel deaktivieren, die kleiner als 2048 Bytes sind, indem man folgenden Eintrag ändert:
jre\lib\security\java.security jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 1024
auf
jdk.tls.disabledAlgorithms=MD5, SHA1, RSA keySize < 2048
Um TLS 1.2 zu verwenden, sollte man mindestens Java7 verwenden, obwohl TLS 1.2 erst ab Java8 standardmäßig aktiviert ist. Außerdem sollte man im HTTPS-Connector die zu verwendenden Chiffrensammlungen explizit festlegen, um zu verhindern, dass der Aufrufer potenziell unsichere Algorithmen verwendet.
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true„ acceptCount="100" maxThreads="150" scheme="https" secure="true" keystoreFile="conf/.keystore" keystorePass="changeit" clientAuth="false" enableLookups="false" sslProtocol="TLSv1.2" ciphers="SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA"/>
Nach Neustart des Severs können Sie mit dem Aufruf
localhost:8080/manager/text/sslConnectorCiphers
kontrollieren, welche Chiffren wirklich aktiv sind und bekommen die Ausgabe:
Connector[HTTP/1.1-8443] SSL_RSA_WITH_RC4_128_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA SSL_RSA_WITH_RC4_128_MD5 TLS_RSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA SSL_RSA_WITH_RC4_128_MD5
Wer noch mehr Informationen zur SSL-Verwendung in Java erhalten möchte, kann in der JRE den Schalter
-Djavax.net.debug=ssl:defaultctx
setzen.
Am besten beginnt man mit Sicherheit von Anfang an, denn gerade default-Werte sind faul(t).
Fazit
Internet-Angriffe und das Ausnutzen bekannter Schwachstellen werden auch in Zukunft eher zunehmen. Das gilt insbesondere durch die vermehrte Nutzung des Internets durch mobile Geräte in unsicheren Umgebungen. Nicht umsonst wurde letztes Jahr die Nummer der Meldedatenbank für Sicherheitsfehler Common Vulnerabilities and Exposures (CVE) um eine weitere Stelle erweitert. Gerade durch die Ablösung von alten Windows-Systemen und damit dem Internet Explorer wird es möglich, komplett auf SSL-Verschlüsselung für HTTPS zu verzichten. Da die großen Internetanbieter und Browserhersteller SSL bereits deaktiviert haben, wird es Zeit, dass man die Standardwerte seiner Tomcat-Konfiguration an die bestehenden Möglichkeiten anpasst, um für den wachsenden Sicherheitsbedarf gerüstet zu sein. Kenne Deine Systeme, Angreifer und Waffen! Deswegen müssen zu einem höheren Sicherheitsniveau auch mehrere Maßnahmen kombiniert werden.
Bei Sicherheit gilt der Pilgersatz, dass „der Weg ist das Ziel“ ist, da man die kritischen Systeme permanent an die bestehenden Anforderungen anpassen muss. Am besten beginnt man mit Sicherheit von Anfang an, denn gerade default-Werte sind faul(t).
Quelle
[1] CVE-Dependency-Check-Werkzeug
Publikationen
- Apache Geronimo. Handbuch für den Java-Applikationsserver, m. DVD-ROM: Frank Pientka