Sunday, 5 February 2017

Perfect SSL Labs Score in 2017


"Even Paranoids Have Real Enemies"



I have written this guide show you how to achieve an A+ at Qualys' SSL Labs SSLServer Test, including full scores in all subcategories, in 2017.

I'll start with an installation of openSUSE Leap 42.1 on which all updates have been applied. The Apache webserver version is 2.4.16 and OpenSSL's version is 1.0.1i-fips. This is important because outdated versions do not support the features needed in this guide.

As I need OpenSSL 1.02, I decided to upgrade to openSUSE Leap 42.2 (Apache/2.4.23, OpenSSL 1.0.2j)

dev:~ # cat /etc/os-release  | grep PRETTY
PRETTY_NAME="openSUSE Leap 42.2"
dev:~ # apachectl -v
Server version: Apache/2.4.23 (Linux/SUSE)
Server built:   2017-01-19 09:35:11.000000000 +0000
dev:~ # openssl version
OpenSSL 1.0.2j-fips  26 Sep 2016
dev:~ #





Establish a baseline



There is room for improvement. In openSUSE's defense I will say that it probably doesn't come with this configuration out of the box. The server has most likely been tampered with, with no regard for https security in mind.

I will not edit the vhosts but instead the ssl-global.conf file.

Certificate


When you generate the CSR and obtain your certificate make sure it meets these standards:

Requirements for your server certificate

  • The key size is at least RSA 4096 bits or equivalent. EC (Elliptic Curve) with 384 bits will also work nicely.
  • Signature algorithm is SHA256withRSA
  • You need the CSR that you used to create the certificate
  • It is trusted, i.e. not self-signed
  • It is not expired, has not been revoked etc. :)

Requirements for the intermediate certificate

  • Same as above, except the key size may be as small as 2048 bits or equivalent
  • Obtain a copy of the intermediate certificate and store it locally on your webserver because you will later configure Apache to send the intermediate certificate to the client along with the server certificate.
  • If the intermediate certificate has an SHA1 signature algorithm, have your server certificate re-issued with a fully SHA256withRSA chain. This should be provided for free by your CA.

This is the bare minimum of what your vhost configuration file should contain:

/etc/apache2/vhosts.d/vhost-ssl.conf
<IfDefine SSL>
<IfDefine !NOSSL>
<VirtualHost _default_:443>


        DocumentRoot "/srv/www/htdocs"
        ServerName dev. Thehastingsfiles.local:443
        ServerAdmin administrator@thehastingsfiles
        ErrorLog /var/log/apache2/error_log
        TransferLog /var/log/apache2/access_log
 
        SSLEngine on

        SSLCertificateFile /usr/local/ssl/dev.crt
        SSLCertificateKeyFile /usr/local/ssl/dev.key
        SSLCertificateChainFile /usr/local/ssl/dev.INTERMEDIATE.crt


        CustomLog /var/log/apache2/ssl_request_log   ssl_combined
        DocumentRoot "/srv/www/htdocs"

</VirtualHost>

</IfDefine>
</IfDefine>

Protocol support

Basically ditching anything older than TLS 1.2 will give you 100 points in protocol support.

/etc/apache2/ssl-global.conf
SSLProtocol TLSv1.2




Cipher Strength and Key Exchange


/etc/apache2/ssl-global.conf
SSLCipherSuite "HIGH:!kRSA:!DHE-RSA-AES128-SHA256:!DHE-RSA-AES128-GCM-SHA256:!DHE-RSA-AES128-SHA:!DHE-RSA-CAMELLIA128-SHA:!ECDHE-RSA-AES128-SHA:!ECDHE-RSA-AES128-SHA256:!ECDHE-RSA-AES128-GCM-SHA256"



A+

For the A+, two more things are needed: Public Key Pinning (HPKP) and Strict Transport Security (HSTS)

Public Key Pinning (HPKP)

For this you are going to need your private key file (here cert.key) and the Certificate Signing request file (here cert.csr)

Find the pin using the private key:


dev:/etc/apache2 # openssl rsa -in /usr/local/ssl/cert.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

writing RSA key

********************************************

Find the backup pin using the CSR file:


dev:/etc/apache2 # openssl rsa -in /usr/local/ssl/cert.csr -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

unable to load Private Key

140386301204112:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:707:Expecting: ANY PRIVATE KEY
********************************************

Find the intermediate cert pin on SSL Labs' website, where you can also see your own pin but not your backup pin:


Installing the pins:

ssl-global.conf

Header set Public-Key-Pins "pin-sha256=\"<insert pin>=\"; pin-sha256=\"<insert backup pin>=\"; pin-sha256=\"<insert intermediate cert pin>=\"; max-age=2592000; includeSubDomains"



Strict Transport Security (HSTS)

ssl-global.conf

Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"

This is it! A+

The complete configuration file

This includes some features not mentioned above which will improve HTTPS performance and security and will show up in the SSLLabs report, but will not further improve your score. These include OCSP stapling and caching (session resumption).

ssl-global.conf

<IfDefine SSL>

<IfDefine !NOSSL>
<IfModule mod_ssl.c>

        #for Stapling Cache
        LoadModule socache_shmcb_module /usr/lib64/apache2/mod_socache_shmcb.so

        AddType application/x-x509-ca-cert .crt
        AddType application/x-pkcs7-crl    .crl

        #Session resumption (caching)
        Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure

        #HTTP Public Key Pinning (HPKP)
        Header set Public-Key-Pins "pin-sha256=\"***=\"; pin-sha256=\"***=\"; pin-sha256=\"***=\"; max-age=2592000; includeSubDomains"

        Header always set X-Frame-Options SAMEORIGIN

        #HTTP Strict Transport Security (HSTS) with long duration

        Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"

        Header always set X-Content-Type-Options nosniff

        <IfDefine SYSTEMD>
        SSLPassPhraseDialog exec:/usr/sbin/apache2-systemd-ask-pass
        </IfDefine>

        <IfDefine !SYSTEMD>
        SSLPassPhraseDialog  builtin
        </IfDefine>

        <IfModule mod_socache_dbm.c>
        SSLSessionCache         dbm:/var/lib/apache2/ssl_scache
        </IfModule>

        <IfModule mod_socache_shmcb.c>
        SSLSessionCache         shmcb:/var/lib/apache2/ssl_scache(512000)
        </IfModule>

        SSLSessionCacheTimeout  300

        SSLRandomSeed startup builtin
        SSLRandomSeed connect builtin

        SSLStaplingCache shmcb:/tmp/stapling_cache(128000)
        SSLUseStapling on
        SSLProtocol TLSv1.2

        SSLCipherSuite "HIGH:!kRSA:!DHE-RSA-AES128-SHA256:!DHE-RSA-AES128-GCM-SHA256:!DHE-RSA-AES128-SHA:!DHE-RSA-CAMELLIA128-SHA:!ECDHE-RSA-AES128-SHA:!ECDHE-RSA-AES128-SHA256:!ECDHE-RSA-AES128-GCM-SHA256"

        # ECDHE key exchange.
        SSLOpenSSLConfCmd Curves P-521:P-384

        SSLHonorCipherOrder on
        SSLCompression      off
        SSLOptions +StrictRequire

</IfModule>

</IfDefine>
</IfDefine>

No comments:

Post a comment