# Public-Key Infrastructure (PKI) Lab
###### tags: `SUTD` `SEED Labs` `Network Security` `Lab`
*Done by: Lin Huiqing (1003810)*
Web view: https://hackmd.io/@ephemeral-instance/B1yPH7Qf_
## Task 1: Becoming a Certificate Authority (CA)
Copy `/usr/lib/ssl/openssl.cnf` into the current directory with the following command:
``` shell
cp /usr/lib/ssl/openssl.cnf .
```
Create subdirectories as specified in the configuration file with the following commands:
``` shell
mkdir demoCA
cd demoCA
mkdir certs crl newcerts
touch index.txt serial
```
Write a single number into the `serial` file so it should look like the following:

Next, we navigate back to the root project directory and generate self-signed certificates for the CA with `openssl req -new -x509 -keyout ca.key -out ca.crt -config openssl.cnf`. The output of the command is stored in `ca.key` and `ca.crt`. The project directory should look something like the following:

The CA's public key certificate `ca.crt` should look something like this:

## Task 2: Creating a Certificate for `SEEDPKILab2020.com`
### Step 1: Generate public/private key pair.
Generate the key pair with `openssl genrsa -aes128 -out server.key 1024`.

This should output a `server.key` file in the same directory.

To view the actual content of `server.key`, run `openssl rsa -in server.key -text`. This will give the private key, namely the following components:
* modulus
* publicExponent
* privateExponent
* prime1
* prime2
* exponent1
* exponent2
* coefficient
### Step 2: Generate a Certificate Signing Request (CSR).
Generate a Certificate Signing Request (CSR) with `openssl req -new -key server.key -out server.csr -config openssl.cnf` and set the common name as `SEEDPKILab2020.com`. This should output a `server.csr` file in the project directory.

The CSR should look something like the below when opened:

### Step 3: Generating Certificates.
As the organisationName in the `server.csr` file ("SEED PKI Lab 2020") does not match the organisationName in the `ca.crt` file ("Poopypaws Pte Ltd"), we have to change the matching rules in the cofiguration file to `policy = policy_anything` as shown below:

Sign the server's CSR with `openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -config openssl.cnf`. This will create a `server.crt` file from the `server.csr` file.
The project directory should then look like this:

The signed certificate `server.crt` then looks like the following:

## Task 3: Deploying Certificate in an HTTPS Web Server
### Step 1: Configuring DNS.
To get the computer to recognise the name of the website `SEEDPKILab2020.com`, we can edit the `/etc/hosts`. Root privilege is required to edit the file. As such, run `sudo nano /etc/hosts` to edit the file. The following line should be added:
``` text
127.0.0.1 SEEDPKILab2020.com
```
The file should look like the following:

### Step 2: Configuring the web server.
First, combine the secret key and certificate into one file:
``` shell
cp server.key server.pem
cat server.crt >> server.pem
```
This creates a `server.pem` file in the project directory as shown:

Launch a web server using `server.pem`:
``` shell
openssl s_server -cert server.pem -www
```
The server can then be accessed with https://SEEDPKILab2020.com:4433. However, Firefox would then show the following screen saying that the "connection is not secure":

Upon clicking "Advanced", we can better pinpoint the error:

The error is due to an invalid security certificate being used by the server, specifically because the issuer of certificate is unknown. This is expected because we generated the CA certificate ourselves. This would not have happened if the server certificate was issued by a legitimate CA like Verisign. We can fix this error by adding our CA's certificate to the browser so that the browser recognises it as a legitimate Certificate Authority.
### Step 3: Getting the browser to accept our CA certificate.
The error mentioned in Step 2 can be fixed by providing the browser with our CA's self-signed certificate.
Navigate to the Certificate Manager part of the preferences. The Certificate Manager looks like this:

Import `ca.crt` on Firefox with the "Trust this CA to identify websites." option checked.

Our CA ("Poopypaws Pte Ltd") should be added into Firefox's list of accepted certificates as seen below.

### Step 4. Testing our HTTPS website.
> Now, point the browser to https://SEEDPKILab2018.com:4433. Please describe and explain your observations.
Now when https://SEEDPKILab2020.com:4433 is accessed, there is no error, but instead, the following page is displayed:

At the same time, the terminal prints "ACCEPT" every time the page is reloaded.

There is no connection error as `ca.crt` has been added to Firefox, allowing Firefox to recognise our CA as a legitimate one. As the browser trusts our CA, it would now trust our certificate by extension, hence loading the page without any errors.
> Please also do the following tasks:
> 1. Modify a single byte of server.pem, and restart the server, and reload the URL. What do you observe? Make sure you restore the original server.pem afterward. Note: the server may not be able to restart if certain places of server.pem is corrupted; in that case, choose another place to modify.
I tried to add a byte to the file by adding a "S" to the "BEGIN RSA PRIVATE KEY" as shown below:

After saving the file, trying to restart the server would result in the terminal showing the following:

As shown above, the server is unable to restart as it is "unable to load the server certificate private key file". This is due to a "bad end line" when reading the file.
Next, I tried to modify the file by adding a "s" in the file, changing "Certificate:" to "Certificates:" as shown below.

After saving the file and trying to restart the server, the server was able to run and the URL could be accessed normally to display the same page.
Next, I tried to add in an additional "=" in at the end of the base64-encoded string wrapped by "BEGIN CERTIFICATE" and "END CERTIFICATE".

After saving the file, we attempt to restart the server. The terminal then prompts for the pass phrase of `server.pem`. After this is entered, an error occurs due to the terminal being "unable to load certificate", as shown below.

The observations above are because the actual certificate in PEM format is only within the `-----BEGIN ...-----` and `-----END ...-----` only. Everything outside of these markers are to make the certificates human-readable. As such, editing these markers or the content wrapped by them would cause errors, while editing anything outside of these markers would not affect programs establishing SSL connections.
Furthermore, we can deduce that the SSL connection first reads the certificate private key file information then the certificate information below. This is from the fact that editing the "RSA PRIVATE KEY" section would cause an error before the pass phrase prompt, while editing the "CERTIFICATE" section would cause an error only after the pass phrase prompt.
> 2. Since SEEDPKILab2020.com points to the localhost, if we use https://localhost:4433 instead, we will be connecting to the same web server. Please do so, describe and explain your observations.
In the case where we use https://localhost:4433 instead, the browser would not be able to connect. Instead, a warning that the "connection is not secure" would pop up, as shown below.


This error is due to an invalid security certificate used for the url, as mentioned above. This error occurs because even though the IP address that both SEEDPKILab2020.com and localhost should point to is the same, the certificate issued was for the Common Name (CN) "SEEDPKILab2020.com" instead of "localhost". As such, when browser tries to use the same certificate when accessing "localhost:4433", the certificate is flagged to be invalid.
## Task 4: Deploying Certificate in an Apache-Based HTTPS Website
> Please use the above example as guidance to set up an HTTPS server for SEEDPKILab2020.com. Please describe the steps that you have taken, the contents that you add to Apache’s configuration file, and the screenshots of the final outcome showing that you can successfully browse the HTTPS site.
First, we navigate to `/etc/apache2/sites-available` where we can find the `VirtualHost` file.
``` shell
cd /etc/apache2/sites-available
```
As root privilege is required to modify the `000-default.conf` file (where `VirtualHost` entries are located), we use the following command to edit the file:
``` shell
sudo nano 000-default.conf
```
Next, we add a new `VirtualHost` entry to the file as shown below as the last entry in the file:
<!--  -->

We first enable the SSL module with:
``` shell
sudo a2enmod ssl
```
This enables the SSL module, as shown below.

Next, test the Apache configuration for errors with:
``` shell
sudo apachectl configtest
```
This configuration file is OK, as printed by the terminal when the command is run (as seen below).

After which, enable the site with:
``` shell
sudo a2ensite default-ssl
```
The terminal will print the following in response:

Finally, the Apache server is restarted with:
``` shell
sudo service apache2 restart
```
A prompt asking for the passphrase would appear, as shown below.

To set the page for the site, run the following commands:
``` shell
sudo mkdir /var/www/SEEDPKILab2020
sudo cp /var/www/html/index.html /var/www/SEEDPKILab2020
```
With root privilege, edit the `index.html` in `/var/www/SEEDPKILab2020`.
To test if the HTTPS site has been successfully set up, go to https://SEEDPKILab2020.com. As the set up is successful, the page would display the `index.html` page edited, as shown below.

The green lock at the start of the address bar indicates that the page is secure and uses HTTPS.
## Task 5: Launching a Man-In-The-Middle Attack
Target website: youtube.com
### Step 1: Setting up the malicious website.
To configure the DNS on the attakcer, add the target website as an entry in `/etc/hosts` as shown below.

Next, add the malicious website as a `VirtualHost` entry to `/etc/apache2/sites-available/000-default.conf` as shown below.

As we are using the same certificate, only the ServerName and DocumentRoot fields are changed.
Restart the Apache server with `sudo service apache2 restart` so as to commit the changes made.
### Step 2: Becoming the man in the middle
The man-in-the-middle is set with the following steps:
1. Add an entry to `/etc/hosts` (with root privilege) on the victim to simulate DNS cache poisoning.
We use the VM with IP `10.0.2.4` as the attacker, while the target site is youtube.com as mentioned. As such, the modified would be as shown below:

2. Add the created CA as an authorised one.
As tasks 1-4 were performed on machine `10.0.2.4`, but the victim is `10.0.2.5`, we use the following command to obtain the `ca.crt` file.
``` shell
scp seed@10.0.2.4:/home/seed/Desktop/50.020NetworkSecurityLabs/lab4 .
```
This copies the certificate `ca.crt` to the current directory on the victim machine.
Next, add `ca.crt` to the browser as an authority, as described in Task 3 Step 3.
### Step 3: Browse the target website.
When the target site is accessed, an error saying that the connection is not secure is displayed as shown below.

As seen in the expanded panel after clicking advanced, the error is caused by an invalid security certificate being used, with the specific error code of `SSL_ERROR_BAD_CERT_DOMAIN`. This is expected, as the certificate used is for SEEDPKILab2020.com, but the domain we are trying to access is youtube.com. Due to this misalignment, an error is flagged.
## Task 6: Launching a Man-In-The-Middle Attack with a Compromised CA
With the private key of the CA, the attacker can sign certificates of fake servers. As such, to impersonate the target site, the attacker can simply generate and sign a certificate that has a common name that is the same as the target site.
To generate and sign a certificate, we can run the following commands in the console:
``` shell
# generate public/private key
openssl genrsa -aes128 -out yt-server.key 1024
# generate CSR
openssl req -new -key yt-server.key -out yt-server.csr -config openssl.cnf
# sign certificate
openssl ca -in yt-server.csr -out yt-server.crt -cert ca.crt -keyfile ca.key -config openssl.cnf
```
Do note that there will be prompts to fill, so the whole series of commands cannot be pasted directly.
Next, add a `VirtualHost` entry in the `/etc/apache2/sites-available/000-default.conf` file, as shown below.

As the DNS cache is assumed to be already poisoned, there is no need to change the `/etc/hosts`, for both the attacker and host.
To display a custom page when the site is accessed, we have to create a html file.
To do so, we first create the `/var/www/YouTube` directory with:
``` shell
sudo mkdir /var/www/YouTube
```
Next, we will copy the default page over to the created directory:
``` shell
sudo cp /var/www/html/index.html /var/www/YouTube
```
The code in `/var/www/YouTube/index.html` can then be modified. The target site can then be accessed on the victim without alerting the browser, as seen below.


As seen above, the content can be modified on both HTTP and HTTPS web servers. Through this, attackers can possibly trick the victim to key in sensitive information, such as login credentials or credit card details. These details can then be used by the attacker for other sites to steal their private information and/or money.