SSL/TLS IReading time: 10 mins
There are some rare occasions when I come across some brilliant pieces of information that I can’t help but share and showcase. This is one such example. This question was asked on the security stack exchange, and well for the most part it’s hidden because no one will search for this particular answer. All the more reason I think it’s incredibly important to bring it to light. The question was asked by Polynomial. The question is answered in an incredible amount of detail by an expert, Thomas Pornin and is covered in this 3-part series. I copied his answer directly with minor changes to keep it as accurate as possible.
SSL (and its successor, TLS) is a protocol that operates directly on top of TCP (although there are also implementations for datagram based protocols such as UDP). This way, protocols on higher layers (such as HTTP) can be left unchanged while still providing a secure connection. Underneath the SSL layer, HTTP is identical to HTTPS.
When using SSL/TLS correctly, all an attacker can see on the cable is which IP and port you are connected to, roughly how much data you are sending, and what encryption and compression is used. He can also terminate the connection, but both sides will know that the connection has been interrupted by a third party.
In typical use, the attacker will also be able to figure out which host name you’re connecting to (but not the rest of the URL): although HTTPS itself does not expose the host name, your browser will usually need to make a DNS request first to find out what IP address to send the request to.
High-level description of the protocol
After building a TCP connection, the SSL handshake is started by the client. The client (which can be a browser as well as any other program such as Windows Update or PuTTY) sends a number of specifications: which version of SSL/TLS it is running, what ciphersuites it wants to use, and what compression methods it wants to use. The server checks what the highest SSL/TLS version is that is supported by them both, picks a ciphersuite from one of the client’s options (if it supports one), and optionally picks a compression method.
After this the basic setup is done, the server sends its certificate. This certificate must be trusted by either the client itself or a party that the client trusts. For example if the client trusts GeoTrust, then the client can trust the certificate from Google.com, because GeoTrust cryptographically signed Google’s certificate.
Having verified the certificate and being certain this server really is who he claims to be (and not a man in the middle), a key is exchanged. This can be a public key, a “PreMasterSecret” or simply nothing, depending on the chosen ciphersuite. Both the server and the client can now compute the key for the symmetric encryption whynot PKE?. The client tells the server that from now on, all communication will be encrypted, and sends an encrypted and authenticated message to the server.
The server verifies that the MAC (used for authentication) is correct, and that the message can be correctly decrypted. It then returns a message, which the client verifies as well.
To close the connection, a close_notify ‘alert’ is used. If an attacker tries to terminate the connection by finishing the TCP connection (injecting a FIN packet), both sides will know the connection was improperly terminated. The connection cannot be compromised by this though, merely interrupted.
Some more details
Why can you trust Google.com by trusting GeoTrust?
A website wants to communicate with you securely. In order to prove its identity and make sure that it is not an attacker, you must have the server’s public key. However, you can hardly store all keys from all websites on earth, the database would be huge and updates would have to run every hour!
The solution to this are Certificate Authorities, or CA for short. When you installed your operating system or browser, a list of trusted CAs probably came with it. This list can be modified at will; you can remove whom you don’t trust, add others, or even make your own CA (though you will be the only one trusting this CA, so it’s not much use for public website). In this CA list, the CA’s public key is also stored.
When Google’s server sends you its certificate, it also mentions it is signed by GeoTrust. If you trust GeoTrust, you can verify (using GeoTrust’s public key) that GeoTrust really did sign the server’s certificate. To sign a certificate yourself, you need the private key, which is only known to GeoTrust. This way an attacker cannot sign a certificate himself and incorrectly claim to be Google.com. When the certificate has been modified by even one bit, the sign will be incorrect and the client will reject it.
So if I know the public key, the server can prove its identity?
Yes. Typically, the public key encrypts and the private key decrypts. Encrypt a message with the server’s public key, send it, and if the server can tell you what it originally said, it just proved that it got the private key without revealing the key.
This is why it is so important to be able to trust the public key: anyone can generate a private/public key pair, also an attacker. You don’t want to end up using the public key of an attacker!
If one of the CAs that you trust is compromised, an attacker can use the stolen private key to sign a certificate for any website they like. When the attacker can send a forged certificate to your client, signed by himself with the private key from a CA that you trust, your client doesn’t know that the public key is a forged one, signed with a stolen private key.
But a CA can make me trust any server they want!
Yes, and that is where the trust comes in. You have to trust the CA not to make certificates as they please. When organisations like Microsoft, Apple and Mozilla trust a CA though, the CA must have audits; another organisation checks on them periodically to make sure everything is still running according to the rules.
Issuing a certificate is done if, and only if, the registrant can prove they own the domain that the certificate is issued for.
What is this MAC for message authentication?
Every message is signed with a so-called Message Authentication Code, or MAC for short. If we agree on a key and hashing cipher, you can verify that my message comes from me, and I can verify that your message comes from you.
For example with the key “correct horse battery staple” and the message “example”, I can compute the MAC “58393”. When I send this message with the MAC to you (you already know the key), you can perform the same computation and match up the computed MAC with the MAC that I sent.
An attacker can modify the message, but does not know the key. He cannot compute the correct MAC, and you will know the message is not authentic.
You said the client sends a key, which is then used to setup symmetric encryption. What prevents an attacker from using it?
The server’s public key does. Since we have verified that the public key really belongs to the server and no one else, we can encrypt the key using the public key. When the server receives this, he can decrypt it with the private key. When anyone else receives it, they cannot decrypt it.
This is also why key size matters: The larger the public and private key, the harder it is to crack the key that the client sends to the server.
How to crack SSL
- Try if the user ignores certificate warnings;
- The application may load data from an unencrypted channel (e.g. http), which can be tampered with;
- An unprotected login page that submits to HTTPS may be modified so that it submits to HTTP;
- Unpatched applications may be vulnerable for exploits like BEAST and CRIME;
- Resort to other methods such as a physical attack.
There is no simple and straight-forward way; SSL is secure when done correctly. An attacker can try if the user ignores certificate warnings though, which would break the security instantly. When a user does this, the attacker doesn’t need a private key from a CA to forge a certificate, he merely has to send a certificate of his own.
Another trick for HTTP is when the login page is not secured, and it submits to an https page. “Great,” the developer probably thought, “now I save server load and the password is still sent encrypted!” The problem is sslstrip, a tool that modifies the insecure login page so that it submits somewhere so that the attacker can read it.
There have also been various attacks in the past few years, such as the TLS renegotiation vulnerability, sslsniff, BEAST, and very recently, CRIME. All common browsers are protected against all of these attacks though, so these vulnerabilities are no risk if you are running an up-to-date browser.
Last but not least, you can resort to other methods to obtain the info that SSL denies you to obtain. If you can already see and tamper with the user’s connection, it might not be that hard to replace one of his/her .exe downloads with a keylogger, or simply to physically attack that person. Cryptography may be rather secure, but humans and human error is still a weak factor. According to this paper by Verizon, 10% of the data breaches involved physical attacks (see page 3), so it’s certainly something to keep in mind.