Note that, from the perspective of the HTTPS client on machine
B,
no behavioural difference is visible between a direct connection
to the HTTPS server on machine
A or to the
mitm_ssl.py
process on machine
C.
In both cases, you are warned that the certificate obtained is not
trustworthy, since it is
self-signed.
On machine
B, try the following command while
arp_spoof.py
and
mitm_ssl.py are still running on machine
C
For convenience, these lines can be edited in a
SHARED/script.sh file on the host system and then executed
with bash SHARED/script.sh from the virtual machine.
:
echo | openssl s_client -showcerts -connect 192.168.10.1:443 \
2>&1 | grep -E 'subject|issuer'
These are the properties of the certificate from
mitm_ssl.py.
Stop
arp_spoof.py and
mitm_ssl.py on
C, and clear
the ARP caches on
A and
B using
ip neigh flush dev eth0.
Then inspect again the properties of the certificate that
B obtains
by querying
192.168.10.1:443; these are the properties of the
HTTPS server certificate on
A.
Observe that no difference is visible: the
subject and the
issuer are identical.
Self-signed certificates such as the one you generated on
A are
useful for testing purposes, but have no value when deploying a
service.
Indeed, you have just observed that nothing prevents someone from easily
generating another one and tricking a client into believing it is
connecting to the intended site while it is actually connecting to a
completely different one!
It is therefore necessary to provide clients with a way of knowing that
the certificate they receive is indeed that of the site they intend to
visit, and not that of a fraudulent site attempting to impersonate the
original.
The standard approach is to rely on a
certification authority that
signs the certificate after verifying that the organisation
requesting the signature is indeed who it claims to be.
If you ask such a certification authority, for example, to sign a
certificate claiming to belong to a well known bank or government
institution, it will not agree to do so.
Clients are preloaded, during installation, with a
list of trusted
certification authorities; this is what allows them to verify the
authenticity of a signature.
It may be useful for understanding if the session instructor explains
the principle of
certificate signing and verification.
Pages 22 and 24 of the document
Chiffrement_Authentification.pdf
may be used as supporting material.
In this tutorial, it is not intended to use such an external certification
authority, but instead you will create your own.
This solution, a
Public
Key Infrastructure, is very practical for an organisation that wants to
deploy certificates for internal services intended only for staff (not the
general public).
Client machines (those used by staff) only need to know the organisation's
certification authority certificate, and they will automatically be able
to trust services whose certificates have been signed by this internal
certification authority.
On the host system, generate a
certification authority named
S7NSA_CA as follows
For convenience, these lines can be edited in a
SHARED/script.sh file on the host system and then executed
with bash SHARED/script.sh from the virtual machine.
:
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-keyout s7nsa_ca.key -out SHARED/s7nsa_ca.crt \
-subj '/CN=S7NSA_CA' -quiet
Note that the
s7nsa_ca.crt certificate is intended to be shared via
the
SHARED directory, whereas the associated
private key
s7nsa_ca.key remains securely stored on the host system.
On machine
A (the HTTPS server), generate a
certificate signing request and its associated
private key as follows
For convenience, these lines can be edited in a
SHARED/script.sh file on the host system and then executed
with bash SHARED/script.sh from the virtual machine.
:
openssl req -newkey rsa:2048 -nodes \
-keyout /etc/nginx/https_server.key \
-out SHARED/https_server.req \
-subj '/CN=192.168.10.1' -quiet
Note that the
https_server.req certificate request is intended to be
shared via the
SHARED directory, whereas the associated
private key https_server.key remains securely stored on the
server.
On the host system,
sign a certificate from this request
using the certificate and
private key of your
certification authority
For convenience, these lines can be edited in a
SHARED/script.sh file on the host system and then executed
with bash SHARED/script.sh from the virtual machine.
:
openssl x509 -req -days 3650 -set_serial 01 \
-in SHARED/https_server.req \
-out SHARED/https_server.crt \
-CA SHARED/s7nsa_ca.crt -CAkey s7nsa_ca.key
On machine
A (the HTTPS server), replace the old certificate
with the newly signed one:
cp SHARED/https_server.crt /etc/nginx/https_server.crt.
Restart the HTTP/HTTPS server with
systemctl restart nginx.service.
Finally, machine
B (the HTTPS client) must be made aware of the
new certification authority in order to trust certificates
signed by it
For convenience, these lines can be edited in a
SHARED/script.sh file on the host system and then executed
with bash SHARED/script.sh from the virtual machine.
:
cp SHARED/s7nsa_ca.crt /etc/ca-certificates/trust-source/anchors
update-ca-trust
trust extract-compat
Verify that your certification authority
S7NSA_CA is correctly
recognised using
trust list | grep -F S7NSA_CA.
Observe that, from now on, when you connect directly to the HTTPS server,
its certificate is properly signed by this authority
For convenience, these lines can be edited in a
SHARED/script.sh file on the host system and then executed
with bash SHARED/script.sh from the virtual machine.
:
echo | openssl s_client -showcerts -connect 192.168.10.1:443 \
2>&1 | grep -E 'subject|issuer'
Visiting the HTTPS site should now be possible without any warning,
whether using
curl https://192.168.10.1/ or
lynx https://192.168.10.1/.
On machine
C, restart the commands
SHARED/arp_spoof.py eth0 192.168.10.2/192.168.10.1 192.168.10.1/192.168.10.2
and
SHARED/mitm_ssl.py 443 192.168.10.1:443.
New attempts to visit the site from
B should cause the
warnings about the self-signed certificate to reappear.
You have just observed that the mechanism of
certificates signed
by a trusted certification authority is the only way to reliably
authenticate the secure server you are connecting to.