Disable 3DES SSL Ciphers in Apache or nginx

There exists a long list of SSL/TLS ciphers that should be avoided for a proper HTTPS implementation. You can find a near-ideal config for high-security TLS 1.0/1.1/1.2 at cipherli.st. This will get you 90%+ of the way towards a well-configured setup.

However, neither the cipher suites specified at cipherli.st nor the Qualys SSL Test flags CBC-mode 3DES ciphers. These ciphers may be vulnerable to CVE-2016-2183, aka the “Sweet32” attack.

OpenVAS has only recently started flagging these ciphers. Blocking them is quite simple and will only affect the oldest of web browsers, which are inherently insecure without upgrading anyways. Triple DES is a relatively old cipher that has several vulnerabilities published in the last 18 years. Although it used to be a government standard for encryption, it should no longer be used.

Disabling all 3DES ciphers in nginx is easy. You can find where your ciphers are defined by running the following command (assuming your config files are in /etc/nginx/):

grep -r "ssl_ciphers" /etc/nginx/

Once you’ve found the file in question, make sure your cipher list contains ‘!3DES’. For example, as of November 2nd, 2016, this is the cipher list I have chosen to use.

ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!3DES';

Disabling 3DES ciphers in Apache is about as easy too. Find where your ciphers are defined with the following command (again, presuming your Apache config is in /etc/httpd/):

grep -r "SSLCipherSuite" /etc/httpd/

Once you’ve found the file containing your cipher suite, make sure it contains ‘!3DES’. As of today, this is a suitable list:

SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES128-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA384:AES128-GCM-SHA128:AES128-SHA128:AES128-SHA128:AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:!3DES

For both Apache and nginx, after changing your cipher suite, test your config (httpd -t or nginx -t) and restart the service in question.

We’re Officially HSTS Preloaded!

So, I checked today, and after submission to the Chrome HSTS Preloading List, and we are indeed HSTS preloaded. This list is also used for Safari, Firefox, and IE11/Edge. This means that the most recent browsers will never send an HTTP request to this site, even when visiting for the first time. This greatly reduces the opportunity to perform an unencrypted HTTP Man-in-the-Middle attack against this site.

aaronsilber.me in HSTS preload list

Fix Broken “Mixed Content” WordPress 4.4 srcset (Responsive Images)

One of the newest features (and one of the coolest) to be introduced to WordPress core lately has been “responsive image support”. What does this really mean? To be specific, WP implemented the HTML5 <img> srcset (“source set”) attribute.

When it works properly, this attribute solves a couple common problems in web development. By providing the browser with a list of pre-scaled image resolutions it can choose from, a device can intelligently request the best image for the current screen resolution. If you’re using one of the currently supported browsers on a high-resolution screen, it should automatically opt to use one of the larger images specified in srcset. I’ve been doing a lot of testing on my Nexus 6P, which is nearly 520 PPI. You can really tell the difference on screens like that.

Here’s the problem. If you’re using HTTPS with WordPress, but it isn’t in your SITEURL or HOME variables, you will likely end up with plain old HTTP srcset paths. Visiting the site on unencrypted HTTP will work just fine, but the problems show when you try HTTPS. Suddenly, and only on devices that support and choose to use the srcset, most of your images will fail to load. This is called “Mixed Content” – loading insecure resources from a secure page. It’s a pretty bad thing to do, and because of the security hazards, almost all browsers will completely block requests like this to unencrypted HTTP from an HTTPS session.

So, yeah, great – browsers block your responsive images. You could go all-HTTPS, or go all-HTTP, but their is an option for your particular instance.

What do you do?

Solution A: filter wp_image_calculate_srcset and do an easy-peasy str_replace( ‘http://’, ‘https://’ ) making *all* your srcset images SSL. Use this for CloudFlare support.

add_filter( 'wp_get_attachment_url', 'set_url_scheme' );
add_filter( 'wp_calculate_image_srcset', function($sources) {
 $filtered_sources = array();
 foreach($sources as $source_key=>$source) {
  $source['url'] = str_replace('http://','https://', $source['url']);
  $filtered_sources[$source_key] = $source;
 }
 return $filtered_sources;
});

Solution B: filter wp_image_calculate_srcset and attempt to detect the protocol the page was requested with, then only rewrite to https if the page was loaded securely as well. This is nice if it works in your configuration since you don’t incur any HTTPS overhead loading images on an unencrypted page. However, it will not work with CloudFlare. If you’re using CloudFlare, you should make sure HTTPS is on and use Solution A.

add_filter( 'wp_get_attachment_url', 'set_url_scheme' );
add_filter( 'wp_calculate_image_srcset', function($sources) {
 $page_protocol = ( !empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443 ) ? "https" : "http";
 foreach ( $sources as $size => $source ) {
  if ( stripos( $source['url'], $page_protocol ) !== 0 ) {
   // we can't find the current page protocol at the beginning of the srcset...
   $new_url = str_replace( $source_protocol . '://', $page_protocol . '://', $url );
   $sources[$size]['url'] = $new_url;
  }
 }
 return $sources;
});

Solution C: update siteurl and home to start with https://. This will make your whole site SSL. Please make sure your certs and redirects are all okay before doing this, or there’s a good chance you’ll lock yourself out of your install.

 

Fresh Start

Off to a fresh start on a new infrastructure provider. WP Engine wasn’t going to work out – their SSL costs were much too high. This site is now proudly secured through Let’s Encrypt, utilizing site-wide HTTPS. HSTS preload headers are also set and submitted for inclusion in browser preload lists. This proper implementation of TLS enables secure transmission of data from this server to you.

Screenshot of A+ Rating on Qualys SSL Labs