Checking SSL certificates on a browser is easy. Just click the green lock icon and you’re good to go. But what if doing the same in a more hacker way? This is where openssl comes into play.

Let’s start by checking the SSL certificate of this website:

openssl s_client -connect www.serhatdundar.com:443
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA
depth=0 C = US, ST = California, L = San Francisco, O = "GitHub, Inc.", CN = www.github.com
---
Certificate chain
 0 s:/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=www.github.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIHMDCCBhigAwIBAgIQAkk+B/qeN1otu8YdlEMPzzANBgkqhkiG9w0BAQsFADBw
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
dXJhbmNlIFNlcnZlciBDQTAeFw0yMDA1MDYwMDAwMDBaFw0yMjA0MTQxMjAwMDBa
MGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxHaXRIdWIsIEluYy4xFzAVBgNVBAMTDnd3
dy5naXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsj49
...
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=www.github.com
issuer=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 3673 bytes and written 289 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Session-ID-ctx:
    Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - xx xx 60 d0 86 88 c0 26-2e 67 c0 e0 01 84 09 ab   .,`....&.x......
    0010 - xx xx 95 f2 fa fa 1f f6-01 06 e3 99 23 2d 69 9a   i...........#-x.
    0020 - xx xx d1 f6 98 35 b5 f4-8f 91 47 b1 8e a6 d4 d2   *....6....G.....
    0030 - xx xx b2 f4 61 f1 b0 7d-43 cb 66 62 c6 15 52 ad   \*..x..}C.fb..R.
    0040 - xx xx c3 f9 a9 f3 f8 e7-f2 7f b8 d3 0e 02 d2 da   /...x...........
    0050 - xx xx 0f 8f c1 1c 6e b3-f0 ae 4c ac 4e f6 8d 7c   g.....x...L.N..|
    0060 - xx xx 3b 2a 77 b3 c2 f0-2b e3 9f 73 1e db 07 6c   /.;*x...+..s...l
    0070 - xx xx a3 b5 42 74 de 4b-55 73 15 cf b0 97 c7 84   <...Bx.KUs......
    0080 - xx xx 65 ee cc 68 35 68-76 ef 7b 4a 7b 41 b3 94   ..e..x5hv.{J{A..
    0090 - xx xx 57 3f 74 a8 e8 0a-ec de 8b 77 49 f9 33 b0   `0W?x......wI.3.

    Start Time: 1643082971
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)

Let’s investigate this response piece by piece.

Certificate Attributes

depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA
depth=0 C = US, ST = California, L = San Francisco, O = "GitHub, Inc.", CN = www.github.com

As you can see above, a certificate consists of several fields. Here is what they mean:

CN: CommonName
OU: OrganizationalUnit
O: Organization
L: Locality
S: StateOrProvinceName
C: CountryName

depth levels reflect the certificate chain, or in other words, the chain of trust:

==> 0. OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
    ==> 1. OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA
        ==> 2. O = "GitHub, Inc.", CN = www.github.com

This leveling means:

  • We trust the certificate issued by Github because we trust Digicert SHA2 Assurance Server.
  • We trust the certificate issued by Digicert SHA2 Assurance Server because we trust DigiCert High Assurance EV Root CA.

But how do we trust DigiCert High Assurance EV Root CA?

If you recall from the “Chain of Trust”, we need to trust someone at the top somehow. Therefore our operating systems and our browsers trust some root CAs, and their self-signed certificates by default.

On an OSx system you can find the list of trusted and blocked certificate issuers by choosing “Go > Go to Folder” in the Finder, and then pasting /System/Library/Security/Certificates.bundle/Contents/Resources/TrustStore.html there.

trust-store

Certificate Chain

Certificate chain
 0 s:/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=www.github.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA

This section is pretty similar to the previous one, it lists the whole chain. As can be seen above, there are two certificates in the chain. Certificate number 0 is the first one we check for validity, and then we continue with certificate 1. By the way, s stands for subject, and i stands for issuer in this representation.

This certificate chain can be summarized as follows:

  • DigiCert High Assurance EV Root CA issued a certificate for DigiCert SHA2 High Assurance Server CA.
  • DigiCert SHA2 High Assurance Server CA issued a certificate for GitHub

SSL Session

This section includes details about the SSL/TLS handshake we’ve just completed.

New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256

SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Session-ID-ctx:
    Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - xx xx 60 d0 86 88 c0 26-2e 67 c0 e0 01 84 09 ab   .,`....&.x......
    0010 - xx xx 95 f2 fa fa 1f f6-01 06 e3 99 23 2d 69 9a   i...........#-x.
    0020 - xx xx d1 f6 98 35 b5 f4-8f 91 47 b1 8e a6 d4 d2   *....6....G.....
    0030 - xx xx b2 f4 61 f1 b0 7d-43 cb 66 62 c6 15 52 ad   \*..x..}C.fb..R.
    0040 - xx xx c3 f9 a9 f3 f8 e7-f2 7f b8 d3 0e 02 d2 da   /...x...........
    0050 - xx xx 0f 8f c1 1c 6e b3-f0 ae 4c ac 4e f6 8d 7c   g.....x...L.N..|
    0060 - xx xx 3b 2a 77 b3 c2 f0-2b e3 9f 73 1e db 07 6c   /.;*x...+..s...l
    0070 - xx xx a3 b5 42 74 de 4b-55 73 15 cf b0 97 c7 84   <...Bx.KUs......
    0080 - xx xx 65 ee cc 68 35 68-76 ef 7b 4a 7b 41 b3 94   ..e..x5hv.{J{A..
    0090 - xx xx 57 3f 74 a8 e8 0a-ec de 8b 77 49 f9 33 b0   `0W?x......wI.3.

    Start Time: 1643082971
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)

Here we see two different TLS versions, TLSv1 and TLSv1.2, which might be confusing. The first one (TLSv1/SSLv3) describes the minimum protocol requirement with the negotiated cipher suite, while the second one (TLSv1.2) describes the actual protocol version is currently being negotiated.

  • Protocol: The handshake has been completed by using the TLSv1.2 protocol.
  • Cipher: ECDHE-RSA-AES128-GCM-SHA256 cipher is used during the handshake.
  • Start Time: The handshake started on 1643082971 (UNIX timestamp).
  • Timeout: It’s valid for 7200 seconds (2 hours). After we will need to do another SSL/TLS handshake.
  • Session-ID: The unique session ID created for this SSL/TLS handshake. Will expire after 2 hours. Having a session ID here also means that the server keeps track of state and if a client reconnects with a session ID the server has given out, it can reuse the existing state it tracked there.
  • TLS session ticket: SSL Session tickets provide a mechanism that means we don’t have to keep the same state at the server.

SSL Certificate

What you see here is the SSL Certificate of this website in X.509 format:

-----BEGIN CERTIFICATE-----
MIIHMDCCBhigAwIBAgIQAkk+B/qeN1otu8YdlEMPzzANBgkqhkiG9w0BAQsFADBw
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
dXJhbmNlIFNlcnZlciBDQTAeFw0yMDA1MDYwMDAwMDBaFw0yMjA0MTQxMjAwMDBa
MGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxHaXRIdWIsIEluYy4xFzAVBgNVBAMTDnd3
dy5naXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsj49
6jJ99veEXO7WdxGQZ7idtCnDcjZqQeDiy6057SwXj9yDUVnqhwo/yII8+y6Jpk3g
75LpPpYNjiOwYp/JkpWbpBAd1FWlvXJo/eZS+TwuIYb7JSc2H3NDDKt2VV5SSKQd
XOkDNqq7BisOFp2/TYwCMZboLufwRR5fKxL0nTKIOCwpnH8k//UdWpvTgIixDGLY
QCwHt0fYEo49jFeDaKD4WMBPq6Tx1iKWBhw3HVc/OyvI3yjRAx4Anf/DCSt9YTW6
...
-----END CERTIFICATE-----

If you want to see other certificates in the chain, for example, the certificate of “OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA”, then you need to run:

openssl s_client -connect www.serhatdundar.com:443 -showcerts

You can simply save this certificate to a file named xyz.pem and then parse for the details:

openssl x509 -in xyz.pem -text
Certificate:
  Data:
    Version: 3 (0x2)
    Serial Number:
      02:49:3e:07:fa:9e:37:5a:2d:bb:c6:1d:94:43:0f:cf
  Signature Algorithm: sha256WithRSAEncryption
    Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA
    Validity
      Not Before: May  6 00:00:00 2020 GMT
      Not After : Apr 14 12:00:00 2022 GMT
    Subject: C=US, ST=California, L=San Francisco, O=GitHub, Inc., CN=www.github.com
    Subject Public Key Info:
      Public Key Algorithm: rsaEncryption
        Public-Key: (2048 bit)
        Exponent: 65537 (0x10001)
        .....
    X509v3 Subject Alternative Name:
        DNS:www.github.com, DNS:*.github.com, DNS:github.com, DNS:*.github.io, DNS:github.io, DNS:*.githubusercontent.com, DNS:githubusercontent.com
    ...

    X509v3 Certificate Policies:
        Policy: 2.16.840.1.114412.1.1
          CPS: https://www.digicert.com/CPS
        Policy: 2.23.140.1.2.2

    Authority Information Access:
        OCSP - URI:http://ocsp.digicert.com
        CA Issuers - URI:http://cacerts.digicert.com/DigiCertSHA2HighAssuranceServerCA.crt

After parsing the certificate, you can see many details about it, such as the signature algorithm (sha256WithRSAEncryption), issuer, validity, subject (owner of the certificate), the public key of the subject, and so on. Subject Alternative Name represents all domains that this certificate is valid for.

Protocol and Cipher Testing

If you want to check if a server supports a specific protocol, you can run:

# possible protocol versions: -ssl2, -ssl3, -tls1, -tls1_1, -tls1_2, or tls1_3
openssl s_client -connect www.serhatdundar.com:443 -PROTOCOL_VERSION

If you get an unknown option error while running this command, it means that the openssl version you are using has deprecated this protocol version already. If it’s not deprecated by your openssl version, but also not supported by the server, you should get an ssl handshake failure error.

Similarly, you can test a server to see if it’s accepting a specific cipher:

openssl s_client -connect www.serhatdundar.com:443 -cipher CIPHER-STRING

You can access possible cipher strings as follows:

# all OpenSSL ciphers including NULL ciphers
openssl ciphers -v 'ALL:eNULL'

# all ciphers except NULL and anonymous DH then sort by strength
openssl ciphers -v 'ALL:!ADH:@STRENGTH'

# all ciphers except ones with no encryption (eNULL) or no authentication (aNULL)
openssl ciphers -v 'ALL:!aNULL'

For more details, you can refer to OpenSSL manuals.

Cheers.