Certificate verification when using NoVerifyHTTPAdapter - ssl-certificate

I have some code that uses Exchangelib to process emails. For various reasons, the certificate validation fails and I have to use the usual NoVerifyHTTPAdapter:
from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter
# Tell exchangelib to use this adapter class instead of the default
BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter
This leads me to two questions:
I am now wondering, am I sending and receiving in plain text without encryption? I know that the servers I am using only have port 443 open.
If I am not sending in plain text, is there a way to get the name of the certificate that I am using?
If this question is answered somewhere else, sorry for the inconvenience, it must have slipped in my initial search.

You are not sending in plain text. Your data is still encrypted since you are communicating over HTTPS.
When certificate validation fails, it means that the certificate of the server cannot be validated using any of the root certificates on your local machine that you (or your OS vendor) have chosen to trust, or that the certificate does not match the server that you are communicating with, that the certificate has expired, or any of the other reasons that may cause failure to validate a certificate.
This means that you have no guarantee that the server you are communicating with is in fact the correct server, which leaves you vulnerable to man-in-the-middle attacks and exposing your data to an untrusted server. But the communication channel itself is still encrypted.
There's some more discussion at What are the implications of ignoring SSL certificate verification?
If you absolutely cannot fix the causes of the invalid certificate, your best option is to accept the certificate locally: How to get Python requests to trust a self signed SSL certificate?

Related

Security and getting a certificate: designing a protocol

In the beginning of an SSL query, the client sends a CLIENT_HELLO message.
The server replies with a certificate message that gives the chain of verifications going back to a known trusted agent.
Suppose for efficiency I wanted to store certificates locally for a new protocol. The current design in TLS is always to require getting the certificate. What could happen to a certificate that would require me to know?
I am trying to understand possible attack scenarios. Consider doing online banking, and suppose a certificate has been compromised. In such as case, the bank is not criminal, but they have been hacked and have to issue a new certificate. Is this reasonable?
If you consider that the bank itself is corrupt, then it seems to me there is no point in worrying about the certificate since they have your money and can just steal it. If the entity you are dealing with goes criminal, does the certificate matter?
Under what circumstances can certfiicates be revoked? I am trying to understand why SSL sends the certificate each time -- it seems really wasteful, but there is probably a good reason.
Would it be possible instead to keep all certificates stored on the client, but check a timestamp with a trusted server? It seems like one could at least send less data across the network
TLS Certificate message after `ServerHello is mandatory in mostly cases, so caching won't have any useful effect. See RFC5246
7.4.2. Server Certificate
When this message will be sent:
The server MUST send a Certificate message whenever the agreed- upon key exchange method uses certificates for authentication (this includes all key exchange methods defined in this document except DH_anon). This message will always immediately follow the ServerHello message.
TLS has its own methods to improve performance. When client sends a valid session_id in ClientHello the session can be resumed and the parties must proceed directly to the Finished messages
Also RFC5077 specifies how to resume sessions without server-side state
EDITED - added comments to specific questions
Suppose for efficiency I wanted to store certificates locally for a new protocol. The current design in TLS is always to require getting the certificate. What could happen to a certificate that would require me to know?
"always" is not correct. TLS sends certificates during handshake. Once the shared key is negotiated, the session can be resumed later by client using sessionid (the usual behaviour). Then, the server does not send the certification chain.
The server sends the certification chain. The client must verify that the presented certificate is reliable:
checking a digital signature performed with the private key of the server certificat
the certificate is issued by a trusted CA. Is supposed that client has a trust store with the root certificates of the certification authorities it trust. The client builds the certification chain presented by server until it finds the root certificate in local truststore
You can perfectly skip the sending of certificates from the server in the second step step if client has a copy of the server certificate in a local truststore
I am trying to understand possible attack scenarios. Consider doing online banking, and suppose a certificate has been compromised. In such as case, the bank is not criminal, but they have been hacked and have to issue a new certificate. Is this reasonable?
In this scenario the attacker could make a MITM attack. The certificate must be revoked by CA and client should check revocation. This is out of scope of TLS
If you consider that the bank itself is corrupt, then it seems to me there is no point in worrying about the certificate since they have your money and can just steal it. If the entity you are dealing with goes criminal, does the certificate matter?
Seems in this case the certificate is the least of the problems...
Under what circumstances can certfiicates be revoked?
Each CA stablish its own procedure. There is no a standard but there are "good practices": When certificate data changes (e.g email) or becomes invalid (Representative of a company), after a renewal revoke the older one, when key is compromised or certificate is lost
Would it be possible instead to keep all certificates stored on the client, but check a timestamp with a trusted server?
Yes it is possible as commented above: Verify a digital signature, verify revocation and stablish a refreshing mechanism
But if you're looking for performance comparing with TLS, the session resumption will probably have better results

Ok to accept self-signed certificate if I control both server and client?

I have an app going into production. It has a java client and a java server, both of which are always the same, and under my team's control. We are using https.
Is it OK in this situation to issue a self-signed certificate and accept it on the client? Is there any risk there?
HTTTPS is to protect the connection between server and client and you don't control this connection fully just by controlling both server and client. If you accept any self-signed certificate just because you control server and client then you would also accept a certificate from a man in the middle, i.e. this would be insecure.
What you can do is to hard code the expected certificate in the client, i.e. certificate pinning. This way you only accept this specific certificate and a man in the middle attack using another certificate is not possible.

Use multiple SSL certificates per domain with HAProxy

When the SSL certificate is revoked, some browsers (including modern ones) don't fetch the new certificate from the server, so about 0.1% of the clients are getting "Revoked certificate" error page and they can't access the service securely. The problem on the client side is solved by clearing browser's cache. However not everybody does it. Most people just close the page as fast as they can, as the error message tends to say "the authenticity of the received data could not be verified" and "report this broken site"..
Is there a way to configure HAProxy, which is working as SSL offloader in front of the web server cluster, to allow connections to be established using the "old" certificate, while all the negotiations and renegotiations are served using the "new" certificate?
P.S. This problem is partially caused by HAProxy SSL session cache, which is crucial with our load, so it can't be disabled.
The certificate of he server is sent inside each full handshake and a validation of the certificate is only done when a certificate is received and is done against the received certificate, not anything cached. But, it might happen that clients refuse to establish a connection if the fingerprint of the certificates does not match the one they've received earlier within the browser session. Or it might be, that they use implicit certificate pinning (with a browser extension), which will detect if the new certificate conflicts with an earlier received certificate and complain about it.
There is nothing you can do about it. All you get from the client at the start of the SSL handshake is the ClientHello record. This might contain the name of the target host (if SNI is used) but there is no information about any old certificates the client might have seen. This means, that the server has no information on which it could decide, if it should send the new or the older certificate for the same hostname.

Verify what client authentication certificates are sent to server?

Is there a way in browser or through some tool to see what SSL certificate (client authentication) was sent to server in request?
I'd start with something like Burp Suite (Free Edition). It's a darn good proxy for... lots of things.
If your server negotiates the client certificate during the initial handshake (without renegotiation), you should be able to see it using Wireshark: you should see a Certificate message coming from the client (not the one coming from the server), after a Certificate Request message sent by the server.
If renegotiation is used, this is more complicated.
SSL MITM tools (like Fiddler) won't be of any help, since they perform their own handshakes. Such tools can be configured to fool the client into believing they are the real server, by having the client trust their fake server certificate (a trust setting the user can generally set on the client). However, this doesn't work on when using a client certificate, unless the tool performing the handshake (the SSL MITM tool in this case) was handling the client certificate itself. Otherwise the verification message at the end (which the server uses to verify that the client has the private key for the client certificate) would fail. Some of these tools can indeed be configured with a client certificate, but you need to set them up with the corresponding private key: in this case you would know which client certificate was used.
Another way to check would be to check what the browser itself does. How to do it may depend on the browser. Environment variables like SSLDEBUG might be of interest when using Firefox.

Is it safe to use HTTPS without SSL certificates for my own domains?

I'd like to run some encrypted connections between some of my own servers. One can use Curl (or some other mechanism) to connect using HTTPS without SSL certificate verification. I'm using PHP, but the language probably isn't significant for this question.
I'm assuming using HTTPS without a SSL certificate is atleast more secure than doing the exact same connection over plain HTTP, since atleast it's encrypted and an evildoer would have to make a much larger effort to intercept en decrypt the information.
As far as I know an SSL certificate only says "this trusted third party says the server you connect to is owned by the guys that claim to own it". If I connect using my own domainname or IP address, I know I'm the owner. What additional value does an SSL certificate provide if I'm the owner of both ends of a connection?
Not verifying the identity of the server you connect to leaves the connection open to potential MITM attacks. SSL/TLS can be used without certificates (with anonymous cipher suites), but they're insecure (and disabled by default); as the TLS RFC says: "Note that this mode is vulnerable to man-in-the-middle attacks and is therefore deprecated."
In addition, the HTTPS specification itself expects there to be an X.509 certificate.
Checking the identity of the remote party is a necessary element for securing your system. It's not very useful to exchange data secretly with a remote party who may not be who they claim they are (even if the secrecy is guaranteed).
This being said, you don't have to go via a commercial CA. You can either use self-signed certificates, which you would have to import individually into each client as trusted certificate, or create your own institutional CA. There are tools to do this, ranging from OpenSSL's CA.pl (see man-page), TinyCA or OpenCA amongst others. Some operating systems also provide their own small CA capabilities.
If I connect using my own domainname or IP address, I know I'm the
owner. What additional value does an SSL certificate provide if I'm
the owner of both ends of a connection?
The certificate assures you that you're indeed connecting to your machine and that the traffic hasn't been intercepted. That's why you need to check that it's a certificate that you recognise.
SSL certificates are more for the piece of mind of your customers or those using your site. In either case, the data is being transmitted over the same connections - it's just a matter of whether or not a third party is certifying you as being safe.
At my last job, we did all of our internal data transfers at my last job via https/ftps but did not have an SSL certificate until very recently. Since the data transfers were internal, it made no difference.