xavier roche's homework

random thoughts and sometimes pieces of code

Security Is Painful

Where Do You Need Security ?

Well, pretty everywhere. As an open-source programmer maintaining a website, I need:

  1. A GPG key to sign sources for Debian
  2. An appropriate certificates to sign my code on Windows
  3. An appropriate certificate for the https website versions, so that my users can use a secured version, involving multiple sub-domains, with dedicated certificates
  4. An appropriate certificate for the smtp with starttls server, allowing to have a bit more secure channel when sending and receiving emails (oh hay NSA!)
  5. The DNS DNSSEC features, securing a bit my DNS naming system

You’re not obliged to secure everything, of course, but most of the stuff above is pretty standard nowadays, and it’s hard not to fulfill all these requirements.

A GPG key to sign sources on Linux

Debian involves thousands of volunteers across the world collaborating to build a complete operating system, and one key aspect is trust among developers. It means that each developer needs to pass certain validation steps to be accepted, and this includes demonstrating your technical skills and your ability to fit the organization spirit. Another requirement is to identify who is responsible for packaging a program (in my case, httrack), as Debian needs to clearly know who uploaded what.

This seems a bit odd to some people: in a virtual world where anonymity is often considered a requirement, and a right – especially in the open-source community – Debian asks people to identify themselves, and identify the work they do.

But the reason behind is trust and accountability: Debian (and all derivative distributions based on its code base) is used by people who would have a hard time using untrusted binaries. What if a backdoor is injected somewhere, for example ? How can we be sure that uploaded packages haven’t been compromised somehow ? Trust is not an option when privacy and security of users is involved (especially in countries where what you may write on twitter can lead you in jail)

What does it mean for a developer like me ?

  • I had to create a GPG key through gpg --gen-key (well, I already had one)
  • I asked three existing Debian developers to meet them in real life (and gladly paid them a beer! :p) so that they can verify my identity (ie. at least one identity card), and sign my GPG key
  • I need to sign produced sources each time I am doing a release, before uploading them to Debian – uploads won’t be accepted otherwise

Oh, by the way, I’ll need to update my key – Debian will soon require to have more secure keys by discarding the old 1024 “Diffie” keys. This will involve key transition steps, including meeting folks at Debian again to re-sign my key.

Appropriate certificates to sign the Windows installer version

If you do not want your users to have the creepy “The publisher could not be verified, are you sure you want to run this software ?” alert message when attempting to install your program, you need to sign at least the installer.

Microsoft provides a handful utility called signtool.exe to sign executables to be distributed:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\signtool.exe" sign /f "certificate.pfx" /t http://timestamp.verisign.com/scripts/timstamp.dll myprogram.exe

The only problem is that we need an official certificate to do that. Want to have a free PKI like what we have on Debian ? NOPE guys, you need those expensive little pieces of numbers – basically a simple certificate will cost you a thousand dollars. Per year. Yep. Per year.

Fortunately for me, Certum is nice enough to provide free certificates to open-source developers. Thank you, guys!

We only have to create a signing request certificate:

openssl req -new -newkey rsa:2048 -keyout signing.pem -out signing.pem

And copy/paste the certificate request part to the provider.

We then need to convert the produced PEM certificate into a useable PFX one for signtool.exe:

openssl pkcs12 -export -out certificate.pfx -inkey signing.pem -in certificate.pem

Appropriate certificates for https

If you have an online store, or are selling something, having a secured version of your website is just an absolute requirement.

But, increasingly, https is becoming the de-facto standard (especially after the PRISM scandal, and especially considering that nothing will change on the government’s side) pretty everywhere. The upcoming HTTP/2.0 protocol may even make https a requirement for all sites.

Having a secured website is unfortunately conditioned to the broken and expensive HTTPS public key infrastructure.

Fortunately enough, the guys at StartSSL also offer free SSL certificates for everyone. These are “low” level certificates, but this is perfectly fine for me (no, I don’t want the golden-platinum certificate). Thank you too, guys!

Things are a bit complicated when actually setting up Apache.

First, each virtual host needs its certificate:

SSLCertificateFile /etc/apache2/ssl/certs/my-server.pem

We need to get the StartSSL certificate chain locally:

wget http://www.startssl.com/certs/sub.class1.server.ca.pem
wget http://www.startssl.com/certs/ca.pem -O startssl-ca.pem
wget --no-check-certificate https://www.startssl.com/certs/ca-bundle.pem -O startssl-ca-bundle.pem

Then, spend few hours trying to figure out how to mitigate the various known attacks against SSL. Darn. Sheesh. Please give me some feedback if you thing the setup below can be improved :)

# Enable SSL
SSLEngine on

# Disable compression (CRIME attack)
# "Available in httpd 2.2.24 and later"
# SSLCompression off

# Enable only secure protocols: TLSv1, but not SSLv2/SSLv3
SSLProtocol all -SSLv2 -SSLv3

# Perfect forward secrecy + BEAST mitigation
# See <https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy>

# Pay attention to the order ciphers are specified
SSLHonorCipherOrder On
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown

# Certificate global settings
SSLVerifyClient none
SSLCACertificateFile /etc/apache2/ssl/certs/startssl-ca.pem
SSLCertificateChainFile /etc/apache2/ssl/certs/sub.class1.server.ca.pem

You can check whether your setup is fine, using openssl as commandline tool:

openssl s_client -CApath /etc/ssl/cert -showcerts -connect www.example.com:443

And you can also use online tools to control used ciphers, options… if you manage to have 100% to all tests, congratulations!

SMTP with certificates

Yes, you also need to pay a certificate for that. The SSL PKI is definitely broken and mostly a scam. Haha.

Fortunately enough, we may use a free certificate for that, too :)

Note that securing the SMTP transactions is not considered sufficient when exchanging sensitive information – use GPG, guys!

For sendmail, I ended up with something like this:

define(`CERT_DIR', `/etc/mail/certs')
define(`confCACERT_PATH', `CERT_DIR')
define(`confCACERT', `CERT_DIR/CAcert.pem')
define(`confSERVER_CERT', `CERT_DIR/MYcert.pem')
define(`confSERVER_KEY', `CERT_DIR/MYkey.pem')
define(`confCLIENT_CERT', `CERT_DIR/MYcert.pem')
define(`confCLIENT_KEY', `CERT_DIR/MYkey.pem')

dnl Do not choke on missing/invalid client cert
define(`confTLS_SRV_OPTIONS', `V')

O CipherList=ALL

It took me a while to understand that the missing define('confTLS_SRV_OPTIONS', 'V') line was the culprit for rejecting some mails…

One last check to ensure your server is correctly setup:

openssl s_client -CApath /etc/ssl/cert -showcerts -connect smtp.example.com:25 -starttls smtp

Securing the DNS with DNSSEC

At last, securing a DNS server becomes increasingly important, too, especially when governments attempt to hijack it. DNSSEC is not yet mainstream unfortunately, and operating systems can not enforce its use yet (which means that evil dictatorships can still intercept public DNS and corrupt the replies).

DNSSEC seems a bit cumbersome to implement at first glance, but at least the system rely on existing DNS infrastructure, and will not cost you additional fees. You’ll find numerous useful FAQ and blogs explaining how to deploy this thing.

You first need to adjust a bit your own DNS server settings to handle DNSSEC. With BIND 9, this can be done through built-in features:

dnssec-enable yes;
dnssec-validation auto;
dnssec-lookaside auto;
managed-keys-directory "/var/cache/bind";

Then, you need a Key Signink Key (aka. “KSK”) for each domain you own. The key, to be renewed every two years or so, is meant to sign other keys. The idea behind is that this key is to be declared to the upstream registrar, through your own domain administration system, and the registrar will sign it, to certify that it is legit. This allows to build a trust chain up to the root DNSSEC authority, whose certificate is known by DNS resolvers. With this key, you’ll be able to create a shorter-lifespan key, the Zone Signing Keys (aka. “ZSK”), aimed to sign the various entries in your DNS zone. This shorter-lifespan key will be put in your DNS zone among other entries, as a DNSKEY entry (the record contains the public key side).

Here comes the KSK:

dnssec-keygen -r /dev/urandom -a RSASHA256 -b 4096 -n ZONE -f KSK httrack.com

And, at last, you need to create regularly (every two or three months) a new ZSK:

dnssec-keygen -K dnssec/zsk -r /dev/urandom -a RSASHA256 -b 2048 -n ZONE httrack.com

And do not forget to sign your zone each time you need to modify it, using the ZSK key:

dnssec-signzone -K dnssec/zsk -e +3024000 httrack.com
service bind9 reload

The .signed versions of the DNS zones will have to be used in place of the previous unsigned ones (named.conf), of course.

The whole setup is not totally straightforward, and will probably cause headache to newcomers. Using online tools to verify the DNS signed records or to check the DNSSEC setup will be extremely helpful.

TL;DR: Security is sometimes painful, but this must not stop you. Your users are trusting you!