I am using OpenSSL to connect over HTTPS to one of my servers. However I cannot seem to get server verification to work on the client side. From what I understand, not verifying the certificate leaves me open to Man In the Middle attacks, but the certificate verification is basically looking for the ip address and domain name within the certificate to match. (I am saying a lot of things wrong just to get some full detailed responses :) )
So if it's my server, I know its domain name and ip address, and I am using SSL, should I be worried? Then again, couldn't the man in the middle decrypt my ssl data, insert malicious code, re-encrypt, and then forward me my server's certificate anyway?
Lastly, if MITM attacks are an issue, what if I check the certificate with another library first to verify, and then use OpenSSL just not with verification?
Are there any other attacks that could happen?
A certificate binds a public key to an entity (an identity like a person or organization). The binding occurs via a signature from an authority. Validation ensures the signature is present, and the entity presenting the certificate is who they say they are.
The way you identify the peer is through DNS names. If DNS is compromised, or the hostname checks are omitted, then the system crumbles.
So you need to trust both the certification authority and DNS. DNS does not provide authenticity assurances (or more correctly, clients don't use the security mechanisms), so you should consider DNS as untrusted input.
With OpenSSL, you need to do three things in the client. First, you need to ensure the server presents a certificate. Second, you need to verify the chain. Third, you need to perform hostname matching because OpenSSL doe not do it as part of chain verification.
Server Certificate
You need to verify the server has a certificate because some of the protocols and cipher suites don't require a certificate. You can do that with:
Chain Verification
This applies if you have a custom verify callback, but it works with both the standard verification built into OpenSSL and a custom verify callback. To get the verify result from chain verification, perform:
Hostname Verification
OpenSSL prior to 1.0.2 does not verify hostnames. You will have to extract the hostnames from the server's certificate and ensure its the site you visited. If you want to borrow the code, take a look at libcurl and the verification procedure in source file
ssluse.c
.If you want to perform the manual verification against a spec, see RFC 6125, Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS).
For completeness, here's how to fetch the DNS names present in the
Subject Alternate Names
(SAN) of a certificate. You can get theX509*
from a function likeSSL_get_peer_certificate
.There's a sample program on the OpenSSL wiki at TLS Client. It covers the Server Certificate and Chain Verification. You will have to provide the code for Hostname Verification.
If you don't perform validation, you might as well save the cycles and choose an anonymous scheme like
ADH
.There's a lot to it, and there's no single answer. Since you are building clients that know the server a priori, consider moving to a pinning scheme so you can forgo trusting CAs and DNS. See for example, OWASP's Certificate and Public Key Pinning.
Also, read Peter Guttman's Engineering Security. A significant portion of the book discusses the systemic defects in PKI, SSL, TLS and human behavior; and how you can improve your security posture.
Basically there are two verification's for Https:
i) Authenticating certificates provided by the sever/client against each others trust stores. For this you have to implement keystore/truststore for server/client instances and add your certificates to keystore and trusted certificates to trust store. This will accomplish certificate verification.
FYI: Keystore and truststore
ii) On other hand HTTPS will do hostname verification to prevent man in the middle attacks. Basically this verification method will return "true" if ip specified in the https url matches with CommonName presented by the certificate. If you know which ip's to trust you can override this verify method. FYI: Hostname verification