2 Way SSL using Apache - Certificate questions - apache

I've been googling like mad trying to figure this out, but the answer doesn't seem to be clear, or at least, it seems like there are contradictory answers.
I'm tasked with setting up an Apache web server with 2Way SSL authentication. We use verisign to get our certificates, so we have a certificate for the web instance with the correct hostname details, signed by verisign, and an intermediate certificate from verisign. This all works very well.
Now, we need to set up a 2Way SSL connection. The initial expectation is that the client will manage their own certificates, and provide them to us for authentication. More than one client may be connecting, and they should each have access to different resources when they connect.
From what I've read, I'm not sure how this would be done...
This is a pretty good overview, but in this situation, they are using self-signed certificates: https://security.stackexchange.com/questions/34897/configure-ssl-mutual-two-way-authentication
Using these details, it would seem like we would have to make the trusted CA point to the certificate authority that signs the client's certificate.
Is it possible to use the client certificate as the trusted CA (even though it isn't self signed, but signed by a CA) or would we have to put a trusted CA from their signer (and at that point, would a CA bundle that includes all the client certificate authority CAs work?) on the server and then use the SSLRequire statements to limit access to specific details of the certificate?
As a followup, can we use the SSL Certificate that we get from verisign to sign client certificates?

So, after several more hours on google, and some testing, I was able to figure out what I needed to.
If I want to use a certificate signed by verisign or some other public CA, I would have to copy their public intermediate certificate (the one that they use to sign the client certs) to my server and specify it as the SSLCACertificateFile in the configuration. The caveat is that then any cert signed by that CA would be accepted, and that's where the SSLRequire directives can used to narrow that down to specific certificates.
Using the SSLVerifyClient optional_no_ca directive would make it assume that the cert is trusted, even if it isn't, and then I would have to use SSLRequire directives to verify the details are correct, however, anybody could create and sign their own certificate with those details and there would be no way to tell.
Creating my own self signed CA certificate, and then using that to sign the client certificates and issuing them to the clients is the only way to both ensure that the cert isn't a forgery and not requiring SSLRequire directives to ensure that only the people that I specify can connect.
Please comment/correct me if I'm wrong on any of this.

Use:
SSLVerifyClient optional_no_ca
In your Apache config. This will request the client certificate but not validate it against a CA. It will then be up to your local script to examine the resulting environment variables set by Apache such as 'SSL_SERVER_S_DN' and decide whether to allow the request or not.
These mod_ssl environment variables are also what your code needs to look at when determining what resources the client can access.
The full documentation is here mod_ssl although you probably found that already.
A note on client certificates. If you did want to use a CA and leave it to the clients, they may all use different CA's and you would have a job maintaining them all on your server. It would be much better to trust a single CA.
The advantage would be that then you could use the build in SSL support to do all your certificate checks and not write your own solution.
You could enforce a single CA by specifying an on-line provider and using email signing certificates to identify clients. These would work fine, just the Certificate Subject would be an email address instead of a domain name.
Or you could set up your own CA and sign client certificates yourself. This is not too difficult and gives you complete control. Either route would require you to add the CA root certificate (plus intermediates) to a file Apache can read and point 'SSLCACertificateFile' to it.

Related

Should the trusted Root CA be a part of the certificate chain?

I'm setting up 2-way SSL communication between services on different hosts. Let's say I have my own CA called A. A is trusted by all of my services through a centralized jks. Now let's say I have certificate B signed by A. When services send the certificate should they be sending the entire chain B - A, or just B? I believe both tend to work with most implementations.
I tried to find canonical information about this online, but I'm coming up with nothing.
Thanks for the help
As per tls - Validating an SSL certificate chain according to RFC 5280: Am I understanding this correctly? - Information Security Stack Exchange:
the server should send the exact chain that is to be used; the server
is explicitly allowed to omit the root CA, but that's all.
Reference (RFC 5246 - TLS v1.2, sec. 7.4.2. - Server Certificate):
certificate_list
This is a sequence (chain) of certificates. The sender's
certificate MUST come first in the list. Each following certificate
MUST directly certify the one preceding it. Because certificate
validation requires that root keys be distributed independently, the
self-signed certificate that specifies the root certificate
authority MAY be omitted from the chain, under the assumption that
the remote end must already possess it in order to validate it in
any case.
The idea behind the trusted root CA is that it is trusted. Would you expect the browser to trust anything sent by the server just because it includes a root CA? No!
Therefore the root CA must be already at the client and must be trusted there. It should not be included in the certificate chain by the server, but if you do it anyway browsers will simply ignore it.

SSL handshake with intermediate certificate

During SSL handshake, the browser downloads any intermediate certificate from the host web server using the URL provided if needed. I believe browser comes with the pre-installed certificates from public CAs having only the public key of the root certificate.
1) When calling a https url using a standalone java program [https://xyz.com ..which is using Verisign certificate], i do not need to add that Certificate to any truststore since its root public is already available in jdk's cacerts truststore file. Is this correct statement?
2) When i run the same program from application server, it requires to add all the intermediate certificate to server truststore individually. Why this works in different way.
If the trust chain for the servers certificate is: root-intermediate#1-intermediate#2-server and the client (browser) has root as trusted CA in its CA store, it needs a way to verify the servers certificate by checking the complete chain up to the root. And because the client usually has no knowledge of the intermediate CAs the server needs to provide them.
Sometimes it seems to work w/o providing these intermediate CAs. First, the browsers usually cache the intermediate CAs they got and thus if intermediate#2 is the same as already seen by another server the verification will succeed, but only for the clients who visited the other server before :(
Another way is to provide a URL inside a certificate, where the issuer certificate can be downloaded, e.g. server could provide a link to the certificate for intermediate#2, intermediate#2 could provide a link to intermediate#1. In this case the client could download the missing certificates. But, this features is not universally adopted, e.g. some browsers might provide it but SSL libraries outside of the browsers usually don't.

Is it possible to prevent man-in-the-middle attack when using self-signed certificates?

I'm not sure is similar question has been asked before (I couldn't find any), but is it possible to protect Client/Server from Man-In-The-Middle attack?
I'm writing a Client application to communicate with Server. Communication will be SSLv3 based.
I am OK with server's self-signed certificates, but worried about someone else generating same self-signed certificate in the same server name and pretend to be it. My Client application uses OpenSSL library. [Client and Server are thrift based, if it makes any difference]. Can I avoid such attack at the same time maintaining support for self-signed certificates?
Yes.
In short, a self signed certificate is more insecure than a CA certificate only when the client does not know the certificate in advance and therefore has no way to validate that the server is who it says it is.
If you add the self signed certificate to the client and don't accept any other certificate, you're actually as secure (or, one could argue, even more so) than having a certificate authority signed certificate.
The important parts to keep SSL secure with or without a certificate authority are;
The server private key (and in the case of a CA, the private keys of all its roots) is kept secret.
The client knows the server certificate (or its CA root).
You can hard-code the server's certificate and compare it against what you receive.
Or better yet, create a CA certificate and server certificate, signed by the CA. Have the CA trusted on the client (again by hardcoding it in your application) and validate received server certificate using the CA certificate.
If you can protect your private keys well enough, a middleman will not be able to masquerade as you, assuming the user actually looks at the certificate. The problem with self-signed is that if you want the user to add the exception to their browser, or just ignore the warning, then you are exposed to man-in-the-middle attack, because anyone else may create their own certificate.
Of course, "protecting your private keys well enough" is not trivial at all. When you pay for a "Verisign" certificate, you're not paying for their software creating the certificate - you're paying for the security forces they have guarding the building in which the private keys are stored.
That's easy! NOOOO !!! Not anymore than you could prevent a man-in-the-middle attack from certificate issued-by a well-know authority. >:)

SSL client certificate needs special contents?

I have a server with an SSL certificate and clients with SSL cetificates, all are signed by the same CA, and the CA is trusted on the server and clients as a root authority.
However none of the clients I have tried (iphone, chrome, explorer) will send the client certificate when the server requests it, even though they all verify the server certificate fine. They all claim not to have the certificate.
When I look at the client certificate in the certificate/profile/store they all claim it is verified and legit, and all the certificates verify fine using openssl etc.
Does an SSL client certificate need a specific name or other details so that client browsers will know when to use it? Kinda of like how a server certificate has to specify the exact domain as the name on the certificate?
The server is an apache2.2 server, but I don't think its a problem on the servers end.
Client certificates must have appropriate Key Usage and Extended Key Usage extensions set. What is "appropriate" in your case, I don't know for sure but the number of variants in Key Usage is small and you can check various values yourself.
You surely haven't forgot about the private key which should be accessible on the client side, have you?
There's a summary of the key usage and extended key usage extensions to use in this document:
http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html
(Although it is for NSS, it should apply to other products.)
You could also check whether the list of accepted CAs sent by the server is configured properly. This can be seen using openssl s_client -connect the.host.name:443, for example.

Apache Tomcat SSL problem

I'm trying to configure Apache Tomcat to use SSL connection with client authentication (two way authentication). My certificates are CA signed.
If I put CA certificate, together with client certificates, in tomcat truststore everything is OK. If I don't put CA cert in tomcat truststore, Tomcat won't trust to clients.
Do I need CA certificate in tomcat truststore?
If I put CA certificate in truststre then Tomcat will trust to every client that have certificate signed by the same CA.
Yes, you need the CA in the truststore. If you are unwilling to put the CA in the truststore, you should not use the CA.
Regarding your last paragraph, you could also examine the Distinguished Name of the client certificates for further authorization.
You are confusing trust, or authorization, with authentication. The only purpose of SSL certificates is to prove that the peer is who he says he is, i.e. establish his identity. You need to decide whether or not you trust that CA's procedures for verifying identity prior to signing CSRs, and if so put its certificate into the truststore.
Whether you want that identity to access parts of your system is a completely different question which you must solve in a different way, via a database of roles granted to identities. This is something that LDAP is particularly good at, but you can also use a DBMS or even an XML file in Tomcat. Have a look at Tomcat Realms for how to do this.
What you mustn't do is attempt to use the truststore as that database. That's not what it's for, and not the purpose for which it or PKI was designed. Which is why you're having problems trying to use it that way.