HTTPS 如何避免中间人攻击
2022-04-09
As we all know, HTTPS just the HTTP covered with the shell of TLS. This article will put the key point to how the TLS works, and why https can protect user from MITM(man in the middle) attack. Finally give a small example of the OCSP attack which will break down the https, and hijack the https communication.
Take a look at the TLS Cert Chain
In this section, I will talk about Cert chain, OCSP, and show them by openssl cmd.
For example, the client is visiting the hdcjh.xyz, when the TCP connection established, the Server will send its cert chain to the client, which is a bundle of certificate, let's take a look:
openssl s_client -connect hdcjh.xyz:443 -showcerts -servername hdcjh.xyz 2>&1 < /dev/null
Output:
CONNECTED(00000005)
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1P5
verify return:1
depth=0 CN = *.hdcjh.xyz
verify return:1
write W BLOCK
---
Certificate chain
0 s:/CN=*.hdcjh.xyz
i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1P5
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1P5
i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
2 s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=*.hdcjh.xyz
issuer=/C=US/O=Google Trust Services LLC/CN=GTS CA 1P5
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 4679 bytes and written 369 bytes
---
New, TLSv1/SSLv3, Cipher is AEAD-CHACHA20-POLY1305-SHA256
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.3
Cipher : AEAD-CHACHA20-POLY1305-SHA256
Session-ID:
Session-ID-ctx:
Master-Key:
Start Time: 1678868999
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
poll error%
The output can be separated into 2 parts, the first part gives the summary of the entire cert chain, and the second part give each cert data on the cert chain.
So let's focus on the first part, explain it line by line, and then focus on one of the certs on the cert chain, to give more detail explain.
The Cert Chain Summary
The depth=2
means the root cert in this cert chain, C stands for country, O stands for Organization, CN stands for common name. verify return means the openssl is able to verify the cert validity by its root cert.
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1P5
verify return:1
depth=0 CN = *.hdcjh.xyz
verify return:1
write W BLOCK
---
write W BLOCK
indicates that OpenSSL has sent a data block to the server over the SSL/TLS connection.
As we can see, the cert chain of the website hdcjh.xyz
is combined with 3 different cert. When the server only send the cert of depth=0
, the browser will seek for its parent cert through the OCSP(Online Certificate Status Protocol), its parent cert info is stored in the cert data, and then browser will also check its parent, untill found the root cert stored in the system or the browser root cert store. Otherwise the browser will assume the cert is unsafe, and show an alert for user or stop visit this site.
One thing we should know is that checking the cert chain validity maybe slow down the speed of opening the website, since browser need to make a series request for parent cert. One solution is send the entire cert chain when client connects to server.
Let's say we have a cert chain which is composed with host.cert
, middle.cert
and root.cert
, then just concat all the cert data into one file ordered, and save to `cert_chain.cert`, then just use the new cert, then the browser will only check once.
Next, let's take look at one of the cert detail in the cert chain.
The Cert Detail
Let's take a look at the depth=0
AKA "hdcjh.xyz" cert.
First we copy and store the cert data showed previously to local file, here I store the cert into hdcjh.xyz.cert
, the content is:
-----BEGIN CERTIFICATE-----
MIIFZTCCBE2gAwIBAgIRAPg+i1HjYiF4EzocJjYMIY0wDQYJKoZIhvcNAQELBQAw
RjELMAkGA1UEBhMCVVMxIjAgBgNVBAoTGUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBM
TEMxEzARBgNVBAMTCkdUUyBDQSAxUDUwHhcNMjMwMTMwMTczMDI3WhcNMjMwNDMw
MTczMDI2WjAWMRQwEgYDVQQDDAsqLmhkY2poLnh5ejCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAJjzUPtXoVd/TjaTQJXMU4tO28aSY82cBRC5e7BIdNN5
JEqwFmnFmRRiSmjGPp/gvcpOGpa0zYhwfmW6ztgohAPNsGU2FTRMFClSe7TJ4wRQ
VYhhT5hR7T9HrUni+t6a0dcHhGxmszXo1cVdkXWRPUa4MSqivjLJtZf6Zdr81AAj
Iw/YA+j4LtM/QHwNf8qt6ecrWkbjppV6+YM0e9ahcz0jtZ0UscAvMBTz1VSszWJM
csynnmTAGU5O3AOmwbPAXbvLIO41KdHMy0OxKHD3J7FbqcMF4Vz+FgceSPwIrq4f
SPK3aAhpBSnLGK6yLoYrxw1rdN+ODqeoD8mC58L7h9ECAwEAAaOCAnwwggJ4MA4G
A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA
MB0GA1UdDgQWBBQZlI1u7/vqAinrJobLECknt4cZ4TAfBgNVHSMEGDAWgBTV/J4N
3x7K3QiXl24rxV/FK/XsuDB4BggrBgEFBQcBAQRsMGowNQYIKwYBBQUHMAGGKWh0
dHA6Ly9vY3NwLnBraS5nb29nL3MvZ3RzMXA1L0g4Z19ibTlHeHk4MDEGCCsGAQUF
BzAChiVodHRwOi8vcGtpLmdvb2cvcmVwby9jZXJ0cy9ndHMxcDUuZGVyMCEGA1Ud
EQQaMBiCCyouaGRjamgueHl6ggloZGNqaC54eXowIQYDVR0gBBowGDAIBgZngQwB
AgEwDAYKKwYBBAHWeQIFAzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3Jscy5w
a2kuZ29vZy9ndHMxcDUvdlBrUjROSUhSNm8uY3JsMIIBAwYKKwYBBAHWeQIEAgSB
9ASB8QDvAHYAs3N3B+GEUPhjhtYFqdwRCUp5LbFnDAuH3PADDnk2pZoAAAGGA/Hd
qgAABAMARzBFAiBoprivTHpPLs6CSQXlofd2OxXaNFHgFve3M8LUDDJcUwIhAIGV
+AXJv+1Vz4gEeINOxnl/OIKvk+CH1D10SOyTWwY3AHUArfe++nz/EMiLnT2cHj4Y
arRnKV3PsQwkyoWGNOvcgooAAAGGA/HdwwAABAMARjBEAiAr5UpRALlHZiVJkxoA
/wvOtYQAFGXuWLeqbMePT2ZH1AIgaC85HueAxPQK256VIGHM4sIPIiefzlOPrtaA
4gbPIGswDQYJKoZIhvcNAQELBQADggEBAI5hUa7MtzNhy1jwlnVpiKsLlxAus0VI
hDccBYfk0v+4SFa3REVMe9Rh6sY2/eUs882wFP5ui1xlW+UIYobvIYN+cBocqhSZ
JCOgDxOofYno5MvhFJll9iT69R+0OuwhSvEHphX8QvdAtGgduidhEkHfZJlmrAq1
LO/UXKVBU90HymLjE4kTLJR/tfZNdFE+ILV3q8v8Zv7MG2TnlOJQFFwTQCIRqmuO
POZDmLjYTR8PEDu5LOTRjsbOkMEkPml7wvDjSSVrCKnwW26U5mGFU2ro+XY6buV8
R65P92uuwG3uuXVQ+T8y53+BVdOv+sBbBGKAXGWnoNhBNGttsR5A/Is=
-----END CERTIFICATE-----
The cert is encoded to X509 format, so we need to ask Openssl for help:
openssl x509 -in hdcjh.xyz.cert -text -noout
Output:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
f8:3e:8b:51:e3:62:21:78:13:3a:1c:26:36:0c:21:8d
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Google Trust Services LLC, CN=GTS CA 1P5
Validity
Not Before: Jan 30 17:30:27 2023 GMT
Not After : Apr 30 17:30:26 2023 GMT
Subject: CN=*.hdcjh.xyz
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
... omit it...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
19:94:8D:6E:EF:FB:EA:02:29:EB:26:86:CB:10:29:27:B7:87:19:E1
X509v3 Authority Key Identifier:
keyid:D5:FC:9E:0D:DF:1E:CA:DD:08:97:97:6E:2B:C5:5F:C5:2B:F5:EC:B8
Authority Information Access:
OCSP - URI:http://ocsp.pki.goog/s/gts1p5/H8g_bm9Gxy8
CA Issuers - URI:http://pki.goog/repo/certs/gts1p5.der
X509v3 Subject Alternative Name:
DNS:*.hdcjh.xyz, DNS:hdcjh.xyz
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.1
Policy: 1.3.6.1.4.1.11129.2.5.3
X509v3 CRL Distribution Points:
Full Name:
URI:http://crls.pki.goog/gts1p5/vPkR4NIHR6o.crl
1.3.6.1.4.1.11129.2.4.2:
......v..sw...P.c.......Jy-.g.......y6...............G0E. h...LzO...I....v;..4Q....3...2\S.!........U...x.N.y.8......=tH..[.7.u.....|.....=..>.j.g)]...$...4.................F0D. +.JQ..Gf%I..........e.X..l..OfG.. h/9.....
... a...."'..S....... k
Signature Algorithm: sha256WithRSAEncryption
... omit it...
We'll only focus on few important fields:
- The
X509v3 Basic Constraints.CA
tell us this cert is not a CA(certificate authority), can not assign for other certs. - X509v3 Subject Key Identifier is the hash of the current cert
X509v3 Authority Key Identifier
is the hash of parent public key, which is used to check whether the validity of parent cert.OCSP - URI
indicate how we can check the status of the parent cert.CA Issuers - URI
indicate where we can download the parent cert.X509v3 CRL Distribution Points
indicate where we can find the revoked cert list. CRL stands for certificate revocation list
Through the CA Issuers - URI
, we can find and download the parent cert.
Through X509v3 Authority Key Identifier
we can validate whether its the real parent of current cert.
Through OCSP - URI
we can check whether current cert is still active.
Now it's a good time to think, assume you are the man in the middle, and you can manipulate any kind of protocol as you want, can you break down the HTTPS now?
Next step, we will go through the OCSP, after that, we will have a complete sight of HTTPS(or TLS), finally let's pretend as MITM, and try to attack this site: hdcjh.xyz
.
The OCSP response detail
First, download the parent cert:
wget http://pki.goog/repo/certs/gts1p5.der
Convert the cert format from der
to pem
so that Openssl can process this cert:
openssl x509 -inform der -in gts1p5.der -out gts1p5.pem
Make an OCSP request by OpenSSL:
openssl ocsp -issuer gts1p5.pem -cert hdcjh.xyz.cert -url http://ocsp.pki.goog/s/gts1p5/H8g_bm9Gxy8 -header "HOST" "ocsp.pki.goog" -resp_text
Output:
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: D5FC9E0DDF1ECADD0897976E2BC55FC52BF5ECB8
Produced At: Mar 15 06:58:14 2023 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: EC4A2797F8915935139678B3E8C8A21D097B312E
Issuer Key Hash: D5FC9E0DDF1ECADD0897976E2BC55FC52BF5ECB8
Serial Number: F83E8B51E3622178133A1C26360C218D
Cert Status: good
This Update: Mar 15 06:58:14 2023 GMT
Next Update: Mar 22 05:58:13 2023 GMT
Signature Algorithm: sha256WithRSAEncryption
... omit it...
WARNING: no nonce in response
Response Verify Failure
8351957312:error:27FFF076:OCSP routines:CRYPTO_internal:signer certificate not found:/AppleInternal/Library/BuildRoots/9e200cfa-7d96-11ed-886f-a23c4f261b56/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/ocsp/ocsp_vfy.c:89:
hdcjh.xyz.cert: good
This Update: Mar 15 06:58:14 2023 GMT
Next Update: Mar 22 05:58:13 2023 GMT
Let's break down the output line by line:
OCSP Response Data
: Indicates that the following information is related to the OCSP response data.OCSP Response Status
: Indicates the status of the OCSP response. In this case, the status is successful, which is indicated by 0x0.Response Type
: Indicates the type of response, which is a Basic OCSP Response.Version
: Indicates the version of the OCSP response, which is version 1.Responder Id
: Indicates the identifier of the responder, which is a hash value calculated over the responder's public key.Produced At
: Indicates the time at which the OCSP response was produced.Responses
: Indicates the certificate status of the certificate(s) requested.Certificate ID
: Indicates the identifier of the certificate for which the status is being reported.Hash Algorithm
: Indicates the hash algorithm used to hash the issuer name and issuer public key.Issuer Name Hash
: Indicates the hash value of the issuer name.Issuer Key Hash
: Indicates the hash value of the issuer public key.Serial Number
: Indicates the serial number of the certificate for which the status is being reported.Cert Status
: Indicates the status of the certificate, which in this case is good.This Update
: Indicates the time at which the OCSP response was generated.Next Update
: Indicates the time at which the OCSP responder expects to generate the next OCSP response for the same certificate.
The most important thing is that if the OCSP request failed, browser will just assume that current cert is valid, since in some scenario like when you connect to a pubilc wifi like a mall or hotel, they need you login to their system first, if browser take the strict policy, then user will never be able to login.
Can we manipulate HTTPS requests in theory?
Here are several scenarios where HTTPS loses effect:
User accepted cert from untrusted CA
Nowadays, most browsers will notify users it's a dangerous operation.
But if the user ignores the warning, the MITM can be very easy to achieve.
Sometimes we need to inspect the HTTPS stream for debugging, so it's really common for me.
The best efficient tool to achieve this is Charles, but sometimes I prefer to control everything by myself, here is a simple example:
- add DNS route for the domain where we will monitor later. For me, I just edit the
/etc/hosts
, and add my domain / IP mapping. - using
socat
to listen on 443, and connect another point to the real ip of the website.
socat -v -v -d OPENSSL-LISTEN:443,fork,reuseaddr,cert=/path/to/cert,key=/path/to/priv/key,veriy=0 TCP:xxx.xxx.xxx.xxx
Then all the request info will print on the console.
- If you want to record and replay it, add a new socat instance, for example, your HTTPS entrypoint listen on 443, and transmit stream to another plain HTTP entrypoint 4443, finally transmit the stream to the destination. After that, using tcpdump listen on 4443, and record all the data to pcap file.
socat -v -d -d OPENSSL-LISTEN:443,fork,reuseaddr,cert=/path/to/cert,key=/path/to/priv/key,veriy=0 TCP:127.0.0.1:4443
socat -d -d TCP-LISTEN:4443,fork,reuseaddr TCP:xxx.xxx.xxx.xxx:443
tcpdump -q -w stream.pcap 'host localhost and port 4443'
- maybe you want to replay the recorded request, just use goreplay
Install untrusted root certification
If you've ever used the Charles(a local HTTPS debug tool), you of course understand how it works. Which only works when you install its self-signed root cert to your system.
For each outward HTTPS request, Charles will sign a new cert for this website, and then Charles can represent a system-level agent to listen and parse all the HTTPS traffic.
Another example is the China railway tickets website force user to install their root certificate while by the tickets. This is a very high potential risk if the railway department cooperated with the network operator, then all the people who have ever bought the ticket will just run naked under the monitors.
Certificate Authority betrayed us
Just like I used to say if CA betrayed us, everyone will be naked in the network and don't know anything about it.
Maybe FBI is watching my posts right now, and will be coming soon 😄.
Crack the RSA or EC cryptography
It's impossible now. Maybe I will write another post to explain why.
Downgrade attack
HTTPS actually has a lot of bugs at the beginning, but most of them have been fixed with time going on. The Downgrade attack tells the client to use HTTP when the client sends an HTTPS request. But this can be fixed if the server has ever set the HSTS in the response. This indicates browser always uses the HTTPS connection while requests. Unless it's the first time user visit this website.