Building Secure Systems – Part 1
The inspiration for this article are the recent disclosures from WikiLeaks of the CIA operations.
Building secure systems is not an easy task. It is a complex problem, that requires, from software developers to think as hackers and look at the system as a whole, not just review their own code and call it a day.
Here are some of the lessons we have learned during building our Password Manager – Keepassa . I will try to keep this blog post platform antagonistic, as much as possible.
Guidelines to build secure systems.
- Use encryption – encrypt sensitive data with industry-leading algorithms. You can use AES, Serpent ot Two-Fish. Its best to combine two algorithums, to be sure that recent progress in quantitive computing, will not compromise your data.
- Encrypt your encryption keys – All algorithms, mentioned above, use a key (a random byte sequence) to actually encrypt your data. If the keys get out you are screwed. So encrypt the encryption keys using Public/Private keys, or PGP (in short asymmetric encryption algorithms). The main idea here is to encrypt the data with your public key and decrypt it with your private key, which you have to secure. Asymmetric encryption’s performance is not great so use it only to encrypt your symmetric keys.
- Secure your private keys – don’t leave your private keys, unencrypted on your computer. Its best to use a HSM device, but that its not always practical. You can use an encrypted flash drive, or an encrypted file or e specialized database like Java Keystore, but always encrypt your private keys storage.
- Use full-disk encryptio. Using full-disk encryption protects you from the possibility, that someone will physically steal your server.
- Use a strong hash function when hashing sensitive data like passwords. SHA1 is compromised. Its best to use SHA-384 or SHA-512.
- Double hash your sensitive data – for example use SHA512(SHA384(my_password)). By using such an aproach, you can protect your app from rainbow attacks, and use the second hashing function as a salt generator.
- Use only open-source libraries and compilers to build your software. By using popular open-source software that is peer-reviewed you can be sure that security issues will be promptly address.
- Use a separate build server, not connected to the Internet. Don’t release software, that is build on the developer machine. By using a separate build machine you can guarantee that your toolchain is not compromised. As software is build using a variety of tools, linkers and compilers, it is extremely important that those tools are secured and trusted. Ken Thompson, has an excellent article on the subject of trusting trust.
- Secure your network communications. With free services like Let’s Encrypt it’s pure laziness not to use TLS for critical applications.
- Don’t use SSLv3 as it is compromised. Use TLS.
- Configure your application to offer encryption ciphers in a specific order. As not all ciphers are created equal, the SSL negotiation process tries them in a specific order. You can control this order, while configuring your server. Here is a Jetty example:
sslContextFactory.setIncludeCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA","TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", "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_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_DHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA","TLS_RSA_WITH_AES_128_CBC_SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA"); sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA", "SSL_DHE_RSA_WITH_DES_CBC_SHA", "SSL_DHE_DSS_WITH_DES_CBC_SHA", "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"); sslContextFactory.addExcludeProtocols("SSL", "SSLv2", "SSLv2Hello", "SSLv3"); sslContextFactory.setIncludeProtocols("TLSv1","TLSv1.1","TLSv1.2");
Check out Part 2 of this post for additional info on how to build secure systems.