I’ve recently ordered penetration testing for one of our web applications for the first time. I have an extended background in web application security so I was pretty confident about the result. Still, I was very curious about what a professional in security would find. I was happy to find out that our application was very secure and the few findings were low risks and simple recommendations. One of the findings, however, got a lot of my attention. It was that we were supporting weak SSL algorithms.

To be honest, despite knowing OWASP’s top 10 vulnerabilities by heart, I have little understanding of what’s underneath the Secure Socket Layer. I know what I think every web developer should know, meaning, it uses public-key cryptography to encrypt a connection with certificates issued by trusted third parties. In the early days, I would purchase certificates for my domains but now, many providers offer them for free.

TLS Versions

Like a lot of developers, I use Cloudflare as a CDN and reverse proxy. I point my domains to Cloudflare DNS servers and I use them to generate SSL certificates for my DNS records. It’s an easy way to get SSL certificates for free with extra caching of my assets. I’m aware that this technique might not be necessary anymore because there’s a lot of free static hosting that acts as CDN and offer SSL certificates, removing the need for a reverse proxy. However, since Cloudflare manage all my DNS, I still use them by default.

Why do I talk about Cloudflare and what is wrong with it? I had to ask my favorite hired pentester. He told me that my website was using a deprecated version of TLS and also was supporting encryption algorithms that are considered weak. I found out that Cloudflare is using this as a default for all SSL certificates. They enable support of TLS 1.0 by default because they say that not every browser supports the recent versions of TLS (1.2 and 1.3). However, in their documentation, they recommend changing the minimum TLS version to 1.2, which is the standard for the Payment Card Industry (PCI). So, I went on and enabled a minimum TLS version of 1.2 on my websites.

Cipher Categories

What was the other thing he said about the support for weak encryption protocols? The report specifically named this algorithm TLS_RSA_WITH_3DES_EDE_CBC_SHA. I had no idea what that string meant although there are a few parts that I recognize. TLS is the Transport Layer Security. RSA is the Rivest-Shamir-Adleman system for public-key cryptography (I had to search for the exact name of the acronym). I also recognize 3DES as an encryption algorithm and SHA as a hash function. I had no idea what EDE and CBC were but I was told that the CBC algorithm is weak and I should use GCM.

After some research, I found that the Cipher Block Chaining (CBC) mode of operation was considered weak because its implementation was often vulnerable to attacks and Galois/Counter Mode (GCM), a modern mode of operation, is now preferred. I looked to change this in Cloudflare but I couldn’t find the setting anywhere. I tried to view my website’s certificate details in Chrome and I also couldn’t find the details about the algorithm.

I found a tool that is very useful to show the details about my SSL configuration and it’s called testssl.sh. It starts by showing the supported protocols. We can see that the fix for setting the minimum version of TLS 1.2 in Cloudflare worked.

Testing protocols via sockets except NPN+ALPN

SSLv2      not offered (OK)
SSLv3      not offered (OK)
TLS 1      not offered
TLS 1.1    not offered
TLS 1.2    offered (OK)
TLS 1.3    offered (OK): final
NPN/SPDY   not offered
ALPN/HTTP2 h2, http/1.1 (offered)

It also shows the ciphers supported by Cloudflare. This is where I could finally find that the CBC algorithm is supported.

Testing cipher categories

NULL ciphers (no encryption)                  not offered (OK)
Anonymous NULL Ciphers (no authentication)    not offered (OK)
Export ciphers (w/o ADH+NULL)                 not offered (OK)
LOW: 64 Bit + DES, RC[2,4] (w/o export)       not offered (OK)
Triple DES Ciphers / IDEA                     not offered
Obsolete CBC ciphers (AES, ARIA etc.)         offered
Strong encryption (AEAD ciphers)              offered (OK)

This is just the category of cipher but the tool also outputs the full list of ciphers supported and this is where I finally found the TLS_RSA_WITH_3DES_EDE_CBC_SHA that my pentester reported.

Testing for other vulnerabilities

The tool also tests potential vulnerabilities.

Testing vulnerabilities

Heartbleed (CVE-2014-0160)                not vulnerable (OK), no heartbeat extension
CCS (CVE-2014-0224)                       not vulnerable (OK)
Ticketbleed (CVE-2016-9244), experiment.  not vulnerable (OK), no session tickets
ROBOT                                     not vulnerable (OK)
Secure Renegotiation (RFC 5746)           OpenSSL handshake didn't succeed
Secure Client-Initiated Renegotiation     not vulnerable (OK)
CRIME, TLS (CVE-2012-4929)                not vulnerable (OK)
BREACH (CVE-2013-3587)                    potentially NOT ok, "br" HTTP compression detected. - only supplied "/" tested
                                        Can be ignored for static pages or if no secrets in the page
POODLE, SSL (CVE-2014-3566)               not vulnerable (OK), no SSLv3 support
TLS_FALLBACK_SCSV (RFC 7507)              No fallback possible (OK), no protocol below TLS 1.2 offered
SWEET32 (CVE-2016-2183, CVE-2016-6329)    not vulnerable (OK)
FREAK (CVE-2015-0204)                     not vulnerable (OK)
DROWN (CVE-2016-0800, CVE-2016-0703)      not vulnerable on this host and port (OK)
LOGJAM (CVE-2015-4000), experimental      not vulnerable (OK): no DH EXPORT ciphers, no DH key detected with <= TLS 1.2
BEAST (CVE-2011-3389)                     not vulnerable (OK), no SSL3 or TLS1
LUCKY13 (CVE-2013-0169), experimental     potentially VULNERABLE, uses cipher block chaining (CBC) ciphers with TLS. Check patches
RC4 (CVE-2013-2566, CVE-2015-2808)        no RC4 ciphers detected (OK)

I had to take a look at BREACH (CVE-2013-3587) because the tool said I could potentially be vulnerable.

The HTTPS protocol, as used in unspecified web applications, can encrypt compressed data without properly obfuscating the length of the unencrypted data, which makes it easier for man-in-the-middle attackers to obtain plaintext secret values by observing length differences during a series of guesses in which a string in an HTTP request URL potentially matches an unknown string in an HTTP response body, aka a “BREACH” attack, a different issue than CVE-2012-4929.

As the tool said, it’s fine for static pages but my Django sites use HTTP compression (GZipMiddleware) and TLS. I had to check if my Django apps were vulnerable. It turns out Django has built-in protection for this vulnerability.

In order to protect against BREACH attacks, the value of this field is not simply the secret. It is scrambled differently with each response using a mask. The mask is generated randomly on every call to get_token(), so the form field value is different each time.

Conclusion

I learn a lot of things in this (small) journey through the Secure Sockets Layer. TLS 1.2 needs to be manually enabled in Cloudflare for most of my websites and I need to find out how I can remove support for the weak CBC mode of operation. It seems Cloudflare adds support for Custom Cipher Suite settings when purchasing the Advanced Certificate Manager. I’ll need to check the SSL certificates where my app is hosted, they likely offer this for free. Luckily, I now have a neat tool to easily find out!