Skip to content

Commit c6f4be9

Browse files
committed
New Chapter Added - HTTPS Explained
1 parent e67255e commit c6f4be9

File tree

6 files changed

+109
-0
lines changed

6 files changed

+109
-0
lines changed

https.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Securely transporting stuff: HTTPS explained
2+
3+
4+
## The problem
5+
The problem with HTTP without any S is that it sends and receives data in plain text.
6+
7+
#### Well, who can see my data in plain text?
8+
9+
Well, anyone in your local network, your co-workers for example or people sitting around in your favourite cåfe.
10+
11+
#### How will they do it?
12+
13+
Since the data is in plain text, they can just tell the [switch](https://en.wikipedia.org/wiki/Network_switch) to deliver packets to their machine instead of yours by [ARP poisioning](https://en.wikipedia.org/wiki/ARP_spoofing) the ARP table maintained by the `switch` :
14+
![ARP poisioning](/images/arp.png)
15+
16+
Also, the owner of the cafe or your boss in your office can see your data by programming the hub/switch easily since they own and have physical access to it or [wire tapping](https://en.wikipedia.org/wiki/Fiber_tapping) the wire itself coming in to the cafe.
17+
18+
**Bad HTTP!**
19+
20+
21+
## Enters HTTPS
22+
23+
![https](/images/https.gif)
24+
25+
The 'S' in HTTPS stands for Secure i.e. if you are visiting any website on the internet that has the protocol `https` in the URI, then it is most likely secure. No one in the `middle` can sniff your traffic.
26+
27+
### How does it work?
28+
HTTPS encrypts all the data that gets transferred between the browser and the server. The server and the browser uses a symmetric key known to both of them to encrypt the data. The process by which they arrive at the common key is called [TLS handshake](https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake). In simple terms, the server sends its `public key` along with `domain name` embedded in a `certificate` to the browser, the browser sends back a `pre-master secret key` encyrpted using the server's public key. The server decrypts the encrypted message using its private key to obtain the pre-master secret key. Both the browser and the server now converts the pre-master key into the `master secret key` which is eventually used for encryption of all the future communications between server and the browser.
29+
30+
![Encryption](/images/encryption.png)
31+
32+
There is still one problem with the above process, that is, any [man in the middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) can also generate a certificate and pretend to be the origin server and send malicious content to the browser.
33+
34+
To solve that problem browser like Chrome, Firefox, Safari etc. come embedded with information to find out which certificates are genuine. Browsers look for signature in the certificate, the signature on the certificate needs to be from one of the trusted [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority). In simple terms, certificate authorities are certain well-known organisations which everyone knows to be trust worthy (it all boils down to trust). If there is no such signature in the certificate then the browser will display a warning to the user that this connection is not really HTTPS. The server on the other hand need to get the signed certificate from one of the certificate authority by physically verifying their identity(by sending docs etc.).
35+
36+
### How to get HTTPS for my website?
37+
#### There are two ways to get HTTPS to your website
38+
1. Paid
39+
* TODO
40+
2. Free:
41+
* Use [LetsEncrypt](https://letsencrypt.org/). Letsencrypt is free because the whole process is totally automated hence getting rid of the manual cost of configuration, creation, validation, expiration etc.
42+
* To setup, follow the steps mentioned here depending on your server: [Setup steps](https://certbot.eff.org/#ubuntuxenial-nginx)
43+
44+
45+
#### Best practices for https configuration, examples are for [nginx](https://www.nginx.com/) but settings for apache and others are available too ([ssl config generator](https://mozilla.github.io/server-side-tls/ssl-config-generator/))
46+
- [ ] regularly update/patch [openssl](https://www.openssl.org/source/) to the latest version available because that will protect you from bugs like [heartbleed](https://en.wikipedia.org/wiki/Heartbleed) and [many more](https://www.openssl.org/news/secadv/20160503.txt).
47+
- [ ] add this flag in nginx server conf for server-side protection from [BEAST attacks](https://en.wikipedia.org/wiki/Transport_Layer_Security#BEAST_attack)
48+
```
49+
ssl_prefer_server_ciphers on;`
50+
51+
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; #Disables all weak ciphers
52+
```
53+
54+
- [ ] Older versions of ssl protocols have been found to have multiple severe vulnerabilities (ex: [POODLE attack](https://en.wikipedia.org/wiki/POODLE), [DROWN attack](https://en.wikipedia.org/wiki/DROWN_attack)), so support only TLSv1.1 and TLSv1.2. Do not support sslv2 and sslv3. Do [check the adoption](https://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers) to know the trade off of restricting to these versions of TLS.
55+
```
56+
ssl_protocols TLSv1.1 TLSv1.2;
57+
```
58+
59+
- [ ] Default Diffie-Hellman parameter used by nginx is only 1024 bits which is considered not so secure. Also, it is same for all nginx users who use the default config. It is estimated that an academic team can break 768-bit primes and that a nation-state could break a 1024-bit prime. By breaking one 1024-bit prime, one could eavesdrop on 18 percent of the top one million HTTPS domains, so do not use the default DH parameter, locally generate the parameter for more security, also use higher number of bits.
60+
```shell
61+
$ cd /etc/ssl/certs
62+
$ openssl dhparam -out dhparam.pem 4096
63+
```
64+
65+
```
66+
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
67+
```
68+
69+
- [ ] config to enable HSTS(HTTP Strict Transport Security) to avoid [ssl stripping](https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping). This should not be a problem if ALL, yes, if ALL traffic is redirected to https
70+
```
71+
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
72+
```
73+
74+
## Certificate Pinning for apps (and website)
75+
#### What's this now?
76+
In general any user who has an access to the app can see all the API calls even if it HTTPS. To do that he creates a certificate authority and tells the device (Android / iOS) to trust it. Now when you connect to the server it sits in between the server and the app and replaces your server's certificate with the one generated `on the fly` with its certificate (having own public/private `key` pair) signed by his own certificate authority and now he can sit in the middle and act as server for the mobile client and act as client for the server. Sneaky.
77+
78+
#### Wait! Isn't HTTPS supposed to prevent that?
79+
Yes, but HTTPS can only help you when the trusted certificate authorities are actually trust worthy. In this case, the user forced the device to trust his own created certificate authority!
80+
81+
#### So, how do I prevent that?
82+
Certificate pinning - Basically, in your app bundle, hard code the server certificate and before doing any API call check whether the server is really using that same hardcoded certificate or someone tried to sneak in his own certificate.
83+
84+
#### Caution
85+
* In case the certificate changes on the server side you will have to force the users to update the app else the app will stop working.
86+
* If you mess up the certificate pinning, you will have to ask users to update the app else the app will stop working.
87+
88+
#### A better way!
89+
Certificate pinning is a good way to prevent this but there is one better way to ensure no one can snoop in - use `public key pinning`. Generally sites like Google rotates its certificate so you will have to force users to update your app. Instead what you should pin in your app is the `public key` which remains static even when Google rotates its certificate hence not needing any app update. This is called `Public key Pinning`.
90+
91+
* Android and iOS sample code examples:
92+
```
93+
https://www.paypal-engineering.com/2015/10/14/key-pinning-in-mobile-applications/
94+
```
95+
96+
## Precautions for general public
97+
* When you visit a website in your browser, make sure it displays the padlock like this (will be gray in safari)
98+
![padlock](/images/padlock.png)
99+
* If you see striked out padlock and a warning page, then do not proceed, someone might be snooping on your traffic.
100+
* iOS and Android apps have no way to tell if they are encrypting the traffic. Bad luck.
101+
* If you use a mobile phone or laptop provided by the company then they may install certain certificates to be trusted by the device and can easily snoop on all your browsing. You should check if any ca cert is installed in your phone. Steps to check: todo
102+
103+
104+
## Future of HTTPS
105+
Web was built on HTTP protocol which lacks the security bit. Slowly people started to feel the need to have the channel secured, so that led to the birth of HTTPS. Still as of today majority of the websites are HTTP since thats the `default protocol`. If one needs to get HTTPS they use one of the methods mentioned in the section above "how to get https for my website".
106+
107+
It would be awesome if all the websites use `https` instead of `http`. Also, all the browsers should force https, meaning they should fail the request if it is not `https`. Currently this is implemented using `HSTS` preload list but that is optional for websites to opt in but it would be nice if all the websites were forced to be https. This would improve the security of end users. There are lot of people promoting the move to https everywhere.
108+
109+
But there is a problem with upgrading to https, that is, if some website was previously linked as http and now only works with https then that `http link` will break (as the links to this site would not get updated by the linker website). There are plugins to use [HTTPS everywhere](https://www.eff.org/Https-everywhere) which forces all the communication to be on `https://` if possible. But a better [proposal](https://www.w3.org/DesignIssues/Security-NotTheS.html) is to do HTTPS everywhere in the sense of the protocol but not the URI prefix - in that we do not need two different prefixes `http` and `https`, just make http use TLS fundamentally.

images/arp.png

64.3 KB
Loading

images/encryption.png

48.7 KB
Loading

images/https.gif

31.5 KB
Loading

images/padlock.png

3.9 KB
Loading

images/wiretap.png

159 KB
Loading

0 commit comments

Comments
 (0)