Maximize SSL Security in Mac OS X Server's Web Server / by Matt Washchuk

In Yosemite's Web Server, it is still possible to use TLS and perfect foward secrecy ... barely.

3-21-16 Update: Apple released OS X Server 5.1 today (which requires Mac OS X 10.11.4). This update brings support for TLS 1.2. For anyone seriously interested in using OS X Server as a web server, MDM server, or mail server, please consider updating to this latest version.

Long ago, Apple decided to deprecate openssl. Since then, it has still released three new versions of Mac OS X, including three new versions of OS X Server. To this day, the web server in OS X Server remains apache2, and openssl continues to provide the encryption transport for the served sites. This makes no sense, since even in Yosemite, Apple only ships openssl 0.9.8za, which doesn’t include support for TLS 1.1, TLS 1.2, or their updated ciphers.

That’s right: you can’t build an OS X Server web server with anywhere near the security virtually any other server could provide years ago. Apple could have rewritten the web server to take advantage of SecTransport, Apple’s newer framework that Safari uses on Mac OS X and iOS to connect to other servers that support TLS 1.2. But, they didn’t, and it doesn’t appear that will ever change. I have to wonder, though: how long does Apple intend to charge $20 for a server package that allows corporations to create MDM servers for iOS devices, while allowing those servers to become more and more vulnerable to SSL exploits? We shall see.

In the mean time, I wanted to see if I could construct a virtual host file that would allow me to get a decent score at Qualsys SSL Labs’s SSL Test.The best score I’ve been able to achieve is B grade, with 100 points for the certificate, 70 points for protocol support, and 90 each for key exchange and cipher strength (this also assumes you’re using a commercial, rather than self-signed, certificate). More importantly, it is possible to construct a configuration file that supports only TLS 1.0 (the highest layer security OS X Server offers) and perfect forward secrecy on many browsers, with the notable exceptions of IE on Windows and old Java clients. While IE does support forward secrecy ciphers, it does not support any of the TLS 1.0 forward secrecy ciphers in openssl 0.9.8za.

This configuration file gives you forward secrecy as far back as Safari in Mac OS X 10.6.8 and in iOS 6, as well as modern versions of Firefox and Chrome on all platforms. My virtual host file is below. This file is in /Library/Server/Web/Config/apache2/sites/\ 0000_any_443_www.example.com.conf. This assumes your server name is www.example.com (which obviously will be different) and assumes your OS X Server configuration is on your boot volume (which is normal). In the config file below, replace “example.com” with the name of your domain. Note the “example” text in the certificate lines, as well. You’d need to use your certificates.

<VirtualHost *:443>
	ServerName example.com
	ServerAdmin admin@example.com
	DocumentRoot "/Library/Server/Web/Data/Sites/example.com"
	DirectoryIndex index.html index.php /wiki/ /xcode/ default.html
	CustomLog /var/log/apache2/access_log combinedvhost
	ErrorLog /var/log/apache2/error_log
	<IfModule mod_ssl.c>
		SSLEngine On
		SSLProtocol -ALL +TLSv1
		SSLCipherSuite \
"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"
		SSLHonorCipherOrder On
		SSLProxyEngine On
		SSLCertificateFile "/etc/certificates/example.cert.pem"
		SSLCertificateChainFile "/etc/certificates/example.chain.pem"
		SSLCertificateKeyFile "/etc/certificates/example.key.pem"
		SSLProxyProtocol -ALL +TLSv1
		SSLProxyCheckPeerCN off
		SSLProxyCheckPeerName off
	</IfModule>
	<Directory "/Library/Server/Web/Data/Sites/example.com">
		Options All -Indexes -ExecCGI -Includes +MultiViews
		AllowOverride All
		<IfModule mod_dav.c>
			DAV Off
		</IfModule>
		<IfDefine !WEBSERVICE_ON>
			Require all denied
			ErrorDocument 403 /customerror/websitesoff403.html
		</IfDefine>
	</Directory>
</VirtualHost>

Four lines are what really matter here:

  1. SSLEngine On
  2. SSLProtocol -ALL +TLSv1
  3. SSLCipherSuite (and its very long set of ciphers)
  4. SSLHonorCipherOrder On

The SSLEngine On obviously makes SSL work. Without it, you’re just getting plaintext HTTP connections.

The SSLProtocol line tells apache to turn off all forms of SSL encryption and then to turn back on TLS 1.0. This prevents the client from requesting a weaker form of encryption, such as SSL 2 or SSL 3.

The SSLCipherSuite line lists a series of compatible cipher suites that the server can use to encode and decode the data. For anyone wondering, this is based off the Intermediate compatibility list at Mozilla’s Wiki. Many of the ciphers are not available to TLS 1.0 (they require TLS 1.1 or 1.2). Apache just discards the unavailable ciphers.

Then, when we add the SSLHonorCipherOrder line, apache will try to use the ciphers in the order they were written on the SSLCipherSuite line. The list of ciphers have already been written in the order from most secure to least secure, so we want to honor this order.

If you’re not sure how to edit this entire file, then just copy and paste those four lines. If any of the lines already exist in your file, you’ll want to overwrite them. I don’t generally recommend copying and pasting the lines, though, because there are other lines that could interfere with this setup. For example, if you have a line about SSLCompression being on or off, that will prevent your site from loading, since we’ve disabled SSL altogether.

What did we achieve?

  • Forward secrecy on modern Apple platforms, Android platforms, and Windows platforms running Firefox or Chrome. That means you could use OS X Server as an MDM server and actually have somewhat secure connections.
  • Avoided Heartbleed (because openssl on OS X is so old).
  • Mitigated BEAST to a large degree.
  • Eliminated POODLE attack by turning off SSL 3.

What’s missing?

Despite increasing our SSL security, there are some things we can’t do:

  • We can’t further mitigate against BEAST attacks, since we can’t use TLS 1.1 or 1.2.
  • We can’t completely eliminate weak, RC4 ciphers, unless we are willing to eliminate compatibility with IE 8 on XP or Android 2.3.
  • We can’t further mitigate against TLS downgrade attacks because we can’t use high enough levels of TLS to begin with!
  • We can’t use Strict Transport Security (HSTS), and we can’t use OCSP stapling.

I continue to hope that Apple will one day officially support a web server that uses TLS 1.2, but until that day comes, this is the most secure you can get. If you have any questions (or if I made errors), please get in touch.