[Updated 3/15/2019]
Table of Contents
Basic Knowledge
Certificate Selection
Tomcat
Apache
Nginx
IIS 8.5 Windows 2012
IIS 10 Winows 2016
References
Basic Knowledge
These configurations assume that you know that RC4 is bad, weak DH leads to LogJam and 3DES & weak ciphers have no place here. We avoid DROWN, ROBOT, MITM and others.
We only support TLS_ECDHE_ECDSA (ECDSA-256 or ECDSA-384 certificates required) and TLS_ECDHE_RSA (RSA-2048 certificate required and most likely what you have) where appropriate. Certain Tomcat/OpenSSL combinations cannot use this and need TLS_RSA because CAS in conjunction with the horribly old Java implementation of Banner 8 makes it impossible to perform SSO successfully.
Only TLS 1.2 and higher is supported. All others are deemed insecure!
Also, Apache 2.4 is the current supported Apache version and Tomcat should be 8.5.x with Java 8 (LTS).
The following sites should be checked to determine the level of security and to confirm that the configs are active and correct (Note: Observatory can generally show all of the other values, but in brief, grade form.):
https://observatory.mozilla.org/
https://www.ssllabs.com/ssltest/
https://www.htbridge.com/ssl/
https://tls.imirhil.fr/
https://securityheaders.com/
Certificate Selection
Although RSA-2048 (and 4096) is supported, all new servers should be deploying ECC-256 as prime256v1 or ECC-384 as secp384r1. See the DigiCert document on ECC certificates.
Tomcat
Typical configurations will look something like this. [NOTE: You can use port 443 with Tomcat if you have configured jsvc
to start as root, then switch to the Tomcat user. You need to be root in order to use a privileged (<1024) port.]
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" keystoreFile="conf/keystore.jks" keystorePass="changeit" />
[/xml]
We want to allow stronger ciphers and more options to improve our overall score. Out of the box, Tomcat usually gets a C. We can achieve an A without loss of browser support and adding in stronger cipher support in Java.
JCE
Start by retrieving the Latest Java 8 LTS. Unlimited strength has been supported and enabled by default in Java 8u161 and later version.
According to the bug report for JDK-8170157, this is also available in 6u181 and 7u171, but these versions are only available through an Oracle account.
If you cannot run those versions, search Oracle for the JCE Unlimited Strength Jurisdiction Policy Files and following the directions for install.
The server.xml
file entry will look like:
keystoreFile="/path/to/keystore.jks" keystorePass="somethingsecure"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslEnabledProtocols="SSLv2Hello, TLSv1.2"
useServerCipherSuitesOrder="true"
ciphers="TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA"
/>
[/xml]
Restart Tomcat and re-test the site and you should have at least a grade of A.
Apache 2.4
For the security of the Apache server through headers, be sure to enable headers with:
a2enmod headers
Then add the following to /etc/apache2/conf-enalbed/security.conf
. [NOTE: Do NOT uncomment the Content-Security-Policy pieces without first reading the Mozilla Content Security Policy
# These replace the defaults located earlier in the config file. ServerTokens Prod ServerSignature Off #Header always add Strict-Transport-Security "max-age=31536000 ; includeSubDomains" Header always add X-XSS-Protection "1" Header always add X-Content-Type-Options "nosniff" #Header always add Content-Security-Policy "default-src https: 'unsafe-inline'" # the next line is for IE #Header always add X-Content-Security-Policy "default-src https: 'unsafe-inline'" Header always add Referrer-Policy "origin" # Only allow my site to frame itself Header always add Content-Security-Policy "frame-ancestors 'self' " Header always add X-Frame-Options "SAMEORIGIN" Header always unset Server Header always unset X-Powered-By Header always unset X-CF-Powered-By Header always unset X-Mod-Pagespeed
For the security of the content, essentially modify /etc/apache2/sites-enabled/default-ssl.conf
with:
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
#
# TLS session tickets are enabled by default. Using them without restarting the web server
# with an appropriate frequency (e.g. daily) compromises perfect forward secrecy.
# Apache 2.4.11 and later.
SSLSessionTickets off [/bash]
HSTS is great and achieves an A+ with Qualys. However, this cannot be successfully undone due to the duration. So, before putting this in place, please read this first:
The problem that HSTS solves is that of a man-in-the-middle performing SSL stripping. He’s in the middle, communicating with your web server using SSL, but communicating with the client on regular unencrypted HTTP. The client can for sure see that the session is NOT encrypted, but critically, the client doesn’t know that the session is SUPPOSED to be encrypted.
HSTS solves this problem by telling the web browser that all connections to your domain are SUPPOSED to be encrypted until at least a certain date. Thus, your client connects to your web server the first time, realizes that it’s HSTS-enabled, and will from then on (until the HSTS expiration date) refuse to communicate with your domain on regular HTTP. This foils the SSL stripping attack, because the client browser will refuse to talk to the man-in-the-middle on HTTP, and will instead try on HTTPS, and will get either no response from the man-in-the-middle or will get an invalid certificate from the man-in-the-middle.
The prerequisite for enabling HSTS though is that your web server must serve everything as HTTPS, including web pages, graphics, CSS, web services, etc. Once a browser sees the HSTS header, it will no longer be able to load anything from your domain on regular HTTP, so HSTS is inappropriate for servers that serve only some content on HTTPS, but not all of it.
and then edit /etc/apache2/conf-enabled/security.conf
either adding or uncommenting:
[/bash]
Finally, add OCSP stapling to the bottom of the /etc/apache2/sites-enabled/default-ssl.conf
file such that it looks somthing like the following. [NOTE: The directives must appear outside the VirtualHost
stanza.]
# OCSP Stapling SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors off SSLStaplingCache shmcb:/var/run/ocsp(128000)
Nginx
All Nginx servers will receive a grade of at least A, A+ with HSTS.
[bash] server {listen 80 default_server;
#listen [::]:80 default_server;
# Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
#listen [::]:443 ssl http2;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /path/to/signed_cert_plus_intermediates;
ssl_certificate_key /path/to/private_key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# modern configuration. tweak to your needs.
ssl_protocols TLSv1.2;
ssl_ciphers ‘ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256’;
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (31536000 seconds = 1 year)
#add_header Strict-Transport-Security max-age=31536000;
# OCSP Stapling —
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
#ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
resolver <IP DNS resolver>;
#….
}
[/bash]
IIS 8.5 (Windows Server 2012 R2)
After you have installed IIS 8.5, install the IIS rewrite extention.
Copy the following into C:\inetpub\wwwroot\web.config
.
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-XSS-Protection" value="1; mode=block" />
<add name="Referrer-Policy" value="origin" />
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="X-Content-Type-Options" value="nosniff" />
<add name="X-Powered-By" value="""" />
<add name="Content-Security-Policy" value="default-src https: ‘unsafe-inline’; frame-ancestors ‘self’" />
<add name="X-Content-Security-Policy" value="default-src https: ‘unsafe-inline’" />
</customHeaders>
</httpProtocol>
<rewrite>
<outboundRules>
<rule name="Remove Server Response Header">
<match serverVariable="RESPONSE_SERVER" pattern=".*" />
<action type="Rewrite" />
</rule>
</outboundRules>
<rules>
<rule name="Rewrite to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
[/xml]
Get the file IISCrypto.exe
from Nartac Software. Run the program and
- Select Best Practices button.
- Select Schannel (if not alreay).
- Under Protocols, only select TLS 1.2.
- Under Key Exchanges, deselect DH.
- Reboot.
After reboot, confirm that the site achieves at least the scores below.
https://observatory.mozilla.org/ C
https://www.ssllabs.com/ssltest/ A
https://www.htbridge.com/ssl/ A+
https://tls.imirhil.fr/ C
https://securityheaders.com/ A
IIS 10 (Windows Server 2016)
After you have installed IIS 10, install the IIS rewrite extention.
Copy the following into C:\inetpub\wwwroot\web.config
.
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-XSS-Protection" value="1; mode=block" />
<add name="Referrer-Policy" value="origin" />
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="X-Content-Type-Options" value="nosniff" />
<add name="X-Powered-By" value="""" />
<add name="Content-Security-Policy" value="default-src https: ‘unsafe-inline’; frame-ancestors ‘self’" />
<add name="X-Content-Security-Policy" value="default-src https: ‘unsafe-inline’" />
</customHeaders>
</httpProtocol>
<rewrite>
<outboundRules>
<rule name="Remove Server Response Header">
<match serverVariable="RESPONSE_SERVER" pattern=".*" />
<action type="Rewrite" />
</rule>
</outboundRules>
<rules>
<rule name="Rewrite to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
[/xml]
Get the file IISCrypto.exe
from Nartac Software. Run the program and
- Select Best Practices button.
- Select Schannel (if not alreay).
- Under Protocols, only select TLS 1.2.
- Under Key Exchanges, deselect DH.
- Select Cipher Suites.
- Deselect all TLS_RSA_WITH_* ciphers.
- Reboot.
After reboot, confirm that the site achieves at least the scores below.
https://observatory.mozilla.org/ C
https://www.ssllabs.com/ssltest/ A
https://www.htbridge.com/ssl/ A+
https://tls.imirhil.fr/ A
https://securityheaders.com/ A