python-3.xcharles-proxymtls

TLS server is accepting connection from a sibling down chain certificate


I am building a TLS server using python (3.13 on macos) and ssl lib. The setup is very simple:

the ssl context is created as follows:

    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1  # Disable older versions
    context.minimum_version = ssl.TLSVersion.TLSv1_2  # Ensure TLSv1.2 is the minimum
    context.set_ciphers("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384")

    context.load_cert_chain(certfile='tlsserver.fc.crt', keyfile='tlsserver.key')

    context.load_verify_locations(cafile='root.crt')

    context.verify_mode = ssl.CERT_REQUIRED

    return context

My CA has the following tree

                          **** TLS Server
      **** Webservers ***{
Root **                   **** OpenSSL Client
      *
      **** Charles CA *** Charles Client

now the ca for verify_locations has only the root certificate.

I have been trying to connect to the server using openssl s_client and it works ok. If I provide a leaf certificate ossl.crt it is rejected unless I provide -CAfile ca.crt that contains cat webservers.crt root.crt then it works.

However, I started trying charles as a proxy to examine the ssl communication. I created a charles-client.crt from charles-root.crt and put the client crt in charles proxy under Client Certificates for my TLS server host and port.

And then I setup port forwarding from 6001 (charles) to 6000 (tls server). Now I can still contact and authenticate with the server using port 6001 and without any crt or key file openssl s_client -connect localhost:6001 -state and the connection is established.

My question is how can this happen? Charles Proxy is forwarding to 6000 but how is it authenticating with the server? It has a leaf certificate that is from a different branch and neither charles nor the server know anything about Charles CA intermediary certificate. How can the connection be established?

I tried using charles-client.crt with openssl directly and it was rejected. But when I use it with port forwarding it works.

Bare with me as I am trying to learn this but if you can direct me somewhere where I can learn how is this happening? or is my setup wrong?


Solution

  • After checking Charles .keystore manually, I did find a reference to the intermediate CA. It was added as a root CA some time ago but then manually removed from the GUI for another root CA; however, it was not actually deleted from the keystore, and Charles was sending it behind the scenes. I had to reset the keystore, and now the behavior is as expected.