Https for transport in WCF - wcf

What is the best way to implement https security for transport without a certificate? Should I just for instance use basicHttpBinding with SecurityMode to Transport and ClientCredentialType to HttpClientCredentialType? I did it in a way described but then when accessing WSDL I have a ceritificate warning.

I don't think you can have https without a certificate. It can be a self-created one, but then the client needs to explicitly install it in its trusted store.

You cannot. HTTPS is just HTTP tunneled inside of SSL/TLS and SSL/TLS requires the use of a certificate on the server side. If this is for testing, or only use by clients that you control, you can choose to do one of these options in place of paying for a CA-issued certificate.
Use a self-signed certificate. In order for this to work without your client getting a warning, you would need to import the certificate into the clients' trust store (usually part of the browser).
Use a certificate issued by a Certificate Authority (CA) that you control and have that CA's issuing certificate (or root) imported/trusted by all of your clients. This is mos useful if you have multiple servers in your environment and you need all of the clients in your environment to trust them.
If you need external clients to connect to your servers without doing any import/trust on the clients, you will need to procure a certificate from a globally-recognized CA like Verisign.

If you want to encrypt the contents of the messages, as well as HTTPs transport security, a further option you can consider is to use message security. This encrypts just the content of the message and not the transport channel. A potential benefit of this is that the message can be secured passing through intermediate systems, whereas HTTPs is point to point
This will require an X509 certificate on the server, which as with https certificates you can either self-sign or get from a CA like Verisign

Related

Restrict TLS mutual authentication to specific TLS certificates

There is a PKI with a single CA issuing all the x509 certificates in my network.
So on my network all the servers and clients possess a certificate from my CA stored in their corresponding keystore together with the private key. Each server and client has also the CA certificate in a chain file available to validate the trust chain of the peer x509 certificate when TLS mutual authentication is going on. All fine.
Let’s suppose I have now on my network two servers and two clients and I want to make sure Client_A and Server_A succeed with TLS mutual authentication using their x509 certificates, as Client_B and Server_B should do.
At the same time, I want to make sure TLS mutual authentication between Client_A and Server_B will not succeed. (Also valid between Client_B and Server_A).
How can I make the servers and clients in my network not only verifying the trust chain, but also respecting some kind of whitelist?
Maybe this is not feasible on TLS Layer, that is what I want to have clarified.
You can achieve this using any of the below 2 approaches-
Verifying client certificate at TLS layer: Create separate intermediate issuing CA for each client group. For example, for all the clients of Server_A, create a CA named Ca_Client_A. So your chain will look like rootCA -> Ca_Client_A -> client certificates. Import this Ca_Client_A in the trust-store of Server-A. Now Server_A will allow connections to the clients which has issuing ca Ca_Client_A. Similarly, you can create Ca_Client_B intermediate CA for serving client group B by server B.
Verifying client certificate at Application layer: For this, you need to write authentication logic in your application server where you need to put constraints such as allowed client certificate-serial numbers or CN name matching with keyword for successful authentication.
Hope that helps.
There isn't any way (that I know of) to do this at the TLS layer.
Most TLS libraries offer a callback option during the certificate exchange, and that would be the appropriate place to check the certificate against a list. Returning the library-specific version of failure/unacceptable will usually cause a TLS handshake failure, and no data will have been transmitted.
A lot of this depends on the server software you are using, not the TLS standard itself. Some software packages can be configured to trust certificates issued by a particular CA certificate. In your scenario, this would allow ANY certificate issued by your CA to connect to ANY server configured to trust your CA certificate. Other server software can be configured to trust a particular certificate, or certificates with a given subject (distinguished name of the certificate, subjectAltName, etc.) So, it depends on which particular "server" you're trying to connect to. Is this an Apache web server? IIS? Tomcat? The answer varies depending on what server platform we're talking about.

WCF trust client certificates only from one root ca

When securing WCF services with server and client certificates there is an easy way to ensure the identity of the service provider certificate (server certificate), by comparing the public key or finger print of the sender certificate with an expected value.
On http://msdn.microsoft.com/en-us/library/ff648360.aspx this is explained in step 8. You can config your app.config file in the endpoint section with an identity element where you can pass in the expected encoded finger print value of the server certificate. A comparison between received service certificate and expected value ensures I am talking to the server I expect.
But now I consider the servers point of view. The server can have several RootCA certificates in its certificate store. If the client certificate send from the requester was issued (and signed) by one of these RootCA my service will trust this client certificate. How can I ensure that my service will only trust certificates issued by one determined RootCA? And how can I configure the one trusted RootCA?
(I think this could be some kind of an equivalent way of certificate pinning for client certificates issued by on RootCA)
The only way to achieve this would be to roll your own custom x509 certificate validator. Then for each incoming request you can simply check to make sure the client certificate was issued by your root CA. It's actually quite easy to do. You can find the steps to implement this here:
How to: Create a Service that Employs a Custom Certificate Validator

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.

mTLS ( mutual TLS) details

I know that for MTLS , both parties , Client and server exchange certificates. These certificates should be signed by a CA that both parties can trust in order to validate the certificate.
My question is , does MTLS also means in addition to verifying the certificate (if CA is trusted, leaf certificate is trusted) , either side (Server or client) can also do some additional checks like Hostname check or Whether the client connecting to the server is in the list of approved trusted entities?
Can anyone point me to the mTLS specification and what are the overheads in mTLS?
Besides what EJP has said about "MTLS" term, the TLS 1.2 specification doesn't have strict requirements regarding what information is to be checked and in which way.
It's up to the receiving party to decide if the presented certificate is to be trusted or not. This means that for example it's ok for the server to accept only certificates issued by the CA that belongs to the company that owns the server. This is how client-bank access systems often work - they accept only certificates issued by the bank and the common name of such certificate must correspond to the username provided in a web form.
Both parties are free to check any information in the certificate including direct comparison of public key hash (thus only particular keypairs will work no matter what is contained in other certificate properties).
The most up todate RFC regarding this subject is:
https://datatracker.ietf.org/doc/draft-ietf-oauth-mtls/
this is an extension to OAuth 2.0
The purpose of this document is to define a mechanism how TLS certificate is used in a context of replacing Client ID and Secret (aka, Client Credentials)
The standard establishes two mechanisms how a TLS Certificate is used as a client credential, and the associated token flows, and attributes.
The general summary of this is:
(a) Authorization Server: checks the certificate either according to PKI (signed by a valid root) The RFC does not define the options, but they are pretty self-explanatory and depend on the use case. But it can be (1) certificate is signed by a trusted root and, is not revoked, (2) individually recognize each certificate based on some logic.
(b) Resource server checks the token and client certificate (client credential, or CC), and used in the underlying TLS session. Please note that there are no validation checks concerning the certificate or its origin at TLS layer, all checks are performed at an Application layer. The resource server should, therefore, configure the TLS stack in a way that it does not verify whether the certificate presented by the client during the handshake is signed by a trusted CA certificate.
This mechanism becomes particularly interesting in some GDPR context, as it makes it impossible to share tokens between client and the server.
Overall a great feature for privacy, and improved security.
mTLS can be implemented by issuing all parties a CA certificate and adding these to all communicating parties, which is a sort of an access control list. Whoever has their CA certificate in your app's trust store is able to connect.
The trust system however is the same as with TLS in the case of a https connection - you can issue several certificates from the same CA and add the root CA certificate to the trust store of your app. It will trust all certificates issued from the same root. This is arguably easier to set up as you only have to add the app's own certificate and the CA root. However, if you want to revoke a certificate, it becomes a little more complicated.
I wrote a guide to generate certificates here:
https://thoughts-about-code.blogspot.com/2021/12/creating-a-ca-for-mtls-with-openssl.html
First:
Both server and client certificates have to be built with the same CA certificate and key
see : https://github.com/ysimonx/mtls-ssl-generator/blob/main/generate_certificates.sh
So you have to store the CA certificate on both sides :
On the server side : you can allow (this is optional) a client that provides client cert built with the same CA than its own certificate. (see rejectUnauthorized: true)
https: {
requestCert: true,
rejectUnauthorized: true,
key: fs.readFileSync("./certificates/server/serverKey.pem"),
cert: fs.readFileSync("./certificates/server/serverCrt.pem") ,
ca: [fs.readFileSync("./certificates/ca/caCrt.pem")]
}
(exemple for a fastify nodejs https self-signed certificate server)
On the client side : you can allow (this is optional too) a server that provides (or not) the same CA certificate as the client knows
curl -k --cert ./certificates/client/clientCrt.pem --key ./certificates/client/clientKey.pem https://localhost:3000/
(parameter -k : do not verify the server certificate based upon a CA authority)
or
curl --cacert ./certificates/ca/caCrt.pem --cert ./certificates/client/clientCrt.pem --key ./certificates/client/clientKey.pem https://localhost:3000/
if you want the client to match the correct CA cert used by the server
There is no 'MTLS Specification', for the very good reason that there is no such thing as 'MTLS'. You just made it up. The TLS specification, including mutual authentication, is to be found in RFC 2246 as amended.
The TLS APIs should make the peer certificate chain available to the application, so it can do any additional checking it likes.
'MTLS', insofar as it exists at all, refers to an Internet Draft for multiplexed TLS.

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.