How to authenticate a user based on a certificate? - c#

On a Certificate provider, StartSSL, when you register, you put in your email and a password. They generate a certificate (.pfx) which you need to download and install into your browser.
Which was pointed out in comments that it is a Client Certificate.
So when you click login, in Chrome for example, a window popups and asks you which certificate to use. I could have several client certificates and log into separate accounts based on what I select. They warn that if you loose the certificate then you can't log in to the site without them regenerating a new certificate.
I am would like to do this using C# - I would like to generate a client certificate and then use it later to log in as admin without typing in a password.
What are the mechanics of this? How can generate certificates and use them to log in to my site? I would like to do this on a MVC C# site. I don't mind if I need to generate self signed certificates, its only for my own use. At least it gets rid of password forms and brute force attacks.

This is fairly simple, the certificate requirement is an option of the SSL handshake.
First you need to go to SSL options on IIS and check the option to accept and require certificates. This is enough for browsers to automatically pop up the cert selection window and the communication is mutually secured by both server and client certificates.
https://technet.microsoft.com/pl-pl/library/cc753983%28v=ws.10%29.aspx
Then comes the request pipeline. You either need a httpmodule or you just provide a handler for the global application's AuthenticateRequest event. There, you refer to the Request.ClientCertificate
https://msdn.microsoft.com/en-us/library/ms524668%28v=vs.90%29.aspx
You read the certificate's unique properties, for example the thumbprint and you use your local database to find a user record that corresponds to the certificate and you set up the Principal for the request lifetime accordingly.

Related

CAC cards and web servers

I have a client that wants to implement CAC with our website. Usually the user already has access based on the certificates assigned to them.
They want to be validated by entering their CAC pin code when they click a button to log in.
I'm using ActivClient to manage the CAC but I don't know how to have the website communicate with the card reader to have the user input the pin code and validate it.
Is this done through IIS settings or do I have to update my code to somehow communicate with the middleware?
Thanks in advance
The solution we used involved a few configuration changes to IIS as well as some code changes to use the information provided by the CAC.
In IIS (8.0), we just set the Authentication to Anonymous Authentication. In SSL Settings, we checked Require SSL and under Client Certificates, select the Require option.
After you've authenticated, depending on what information you need access to from the certificate, you can access it using this method:
X509Certificate2 certificate = new X509Certificate2(Request.ClientCertificate.Certificate);
This will give you the certificate object that contains the information that the CAC carries. You can access some of these properties by using
certificate.GetNameInfo(X509NameType.SimpleName); //X509NameType.EmailName, etc
I recently dealt with this with the DoD. There is no code involved, all you have to do is set the the IIS site to use Integrated Security (or possibly certificate authentication based on your AD configuration) and turn off the other authentication mechanisms. The browser will then prompt the user for credentials using the method configured in Active Directory, which should show the CAC certificate selection and PIN window if they are using AD correctly. Note that you must also be using HTTPS or the browser will not pass the CAC credentials to the server for security reasons.

How to find out a possible man-in-the-middle the Google way?

I am wondering how is Google able to show messages like Cannot connect to the real mail.google.com or similar? Are the IP addresses of Google servers simply hard-coded within Chrome or is it possible to do a similar thing? This could help making sure clients are not visiting phishing or scams websites.
This errors only shows when trying to access Google related websites, nothing else.
Here is a sample of what Google Chrome shows when trying to connect to Gmail without providing the proxy credentials.
PS: I usually use C# & ASP.NET. I am open to suggestions.
EDIT :
Following the answer from SilverlightFox, is there any way to "request" the pinning of my website certificate? And/Or how to add it to the "STS preloaded list"?
As #Ted Bigham mentioned in comments, this will be achieved via Certificate pinning:-
One way to detect and block many kinds of MITM attacks is "certificate pinning", sometimes called "SSL pinning". A client that does certificate pinning adds an extra step to the normal TLS protocol or SSL protocol: After obtaining the server's certificate in the standard way, the client checks the server's certificate against trusted validation data. Typically the trusted validation data is bundled with the app, in the form of a trusted copy of that certificate, or a trusted hash or fingerprint of that certificate or the certificate's public key. For example, Chromium and Google Chrome include validation data for the *.google.com certificate that detected fraudulent certificates in 2011. In other systems the client hopes that the first time it obtains a server's certificate it is trustworthy and stores it; during later sessions with that server, the client checks the server's certificate against the stored certificate to guard against later MITM attacks.
From What is certificate pinning?:-
some newer browsers (Chrome, for example) will do a variation of cerficiate pinning using the HSTS mechanism. They preload a specific set of public key hashes into this the HSTS configuration, which limits the valid certificates to only those which indicate the specified public key.
HTTP Strict Transport Security (HSTS) is a technology that is implemented via a HTTP response header (sent via HTTPS only) that tells a browser to "remember" that a website is to only be accessed via HTTPS for a period of time. If HSTS is set on www.example.com and the user visits http://www.example.com before max-age has expired, the browser will request https://www.example.com instead and no request will be sent via plain HTTP. HSTS requires that the user has already visited the site in order to have received the header, however a workaround has been implemented by Google in their Chrome browser code:
Google Chrome and Mozilla Firefox address this limitation by implementing a "STS preloaded list", which is a list that contains known sites supporting HSTS. This list is distributed with the browser so that it uses HTTPS for the initial request to the listed sites as well.
Update following question edit
Following the answer from SilverlightFox, is there any way to "request" the pinning of my website certificate? And/Or how to add it to the "STS preloaded list"?
According to this blog post you should contact the browser developers to be included in the HSTS list and have your public key (or CA's) pinned in the browser:
is this domain HSTS-preloaded in Chrome? For now it is hardcoded in the binary and will hopefully grow. You can contact Chromium to have your site included in that list.
and
So right now, the only solution to pin public keys of CAs signing your website certificates would be to contact Chromium team to be included in the code.
The only way to fight the man-in-the-middle is to have some pre-shared knowledge. In this case those are hardcoded certificates of a couple of root authorities that your browser trusts. These root certificates are used by their authority to sign certificates of other authorities which in turn become trustworthy too. A chain of trust is built until you hit the certificate of mail.google.com.
When you go to mail.google.com you are automatically redirected to the HTTPS (note the S!) version of the site. HTTPS means certificates. Your browser downloads the certificate of that site and inspects if the signing chain is rooted by some of the authorities your browser trusts. If not: Big fat warning! Possibly man-in-the-middle spoof going on!
Another thing that might happen is that the redirect from HTTP to HTTPS fails because some firewall between you and Google blocks HTTPS. That might be the warning you are getting.

What part of an x509 certificate should I store in the database to look up a user?

I have a web application that uses Forms Auth against a custom user store. We want to extend our Users entity so we can configure a client certificate to use in lieu of username/password.
I have successfully configured IIS to accept client certificates, and I can inspect the client certificate in my security module's AuthorizeRequest event and validate it. The final step is to be able to associate the provided client certificate with a user. For testing purposes, I am currently recording a certificate's subject name in my Users table, and looking up a user that way.
Of course, that isn't adequate for production. What should I store in my Users table from the client certificate so I can look up and log the user in?
You should use the certificate's thumbprint as the key for storing or looking up the certificate, or for looking up the user given the certificate. More info here: http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.thumbprint.aspx

Install SSL Cert for single application?

I'm creating a Windows Forms application that uses an embedded WebBrowser control to view an intranet web page. The page is provided via https, using a self-signed certificate. I want the certificate to be valid in the context of my application, but don't want to mess with the client's machine itself (by permanently installing a trusted certificate).
Is there any way to programmatically trust a certificate for the lifetime of an application, rather than for the system as a whole?
You can certainly do that. But you may need to do it in two steps. Make a https request first and get the Server certificate and create a truststore on the fly and import the certificate into the truststore. This would be a onetime activity. You may cache this truststore to the filesystem so that you need not do this everytime. Make another https request and use this truststore for validating the subsequent https requests that you will make.

Comparison of the relative merits and appropriate scenarios for the supported WCF authentication credentials

I'm trying to select the correct authentication mechanism for a WCF service. This article explains what the supported credentials are - I just don't understand how to decide between them.
Please could somebody supply an explanation of when each of the authentication options are appropriate to use, and the advantages/disadvantages of each over the others.
For reference, the authentication options are:
None
Basic
Digest
Ntlm
Windows
Certificate
Password
Note: I have seen a great MSDN article on this, but I cannot for the life of me find it anymore.
None:
Pretty straightforward - use this when you don't want to identify or authenticate your users.
Basic and Digest:
These authentication types aren't used much any more, but occasionally you might need to connect to an older web service hosted in IIS, which might be configured to use Basic or Digest authentication. Traffic won't be encrypted. For Basic, the password will be sent in plain text, and for Digest the password will be sent in a poorly encrypted form. Avoid using these authentication types.
NTLM and Windows:
NTLM uses the NT LAN Manager to control security. Windows, by default, will use Kerberos (ie Active Directory) to control security. If Kerberos is not available, it will default to NTLM. Only use NTLM if you specifically need to avoid Kerberos (I cannot think of a scenario where you would want to do this, but part of WCFs greatness is its flexibility).
Certificate:
If your users have their own certificates which can be used to identify them, you might consider using this authentication mode. Passwords can be guessed - it is very hard to guess a certificate, so this is a pretty secure mode of authentication (provided the certificate itself is secure).
Password:
Use Password when you want to create your own method of validating a users username and password. This might involve accessing an existing user credential store in a custom database. You will need to write your own UserNamePasswordValidator - example at http://nayyeri.net/custom-username-and-password-authentication-in-wcf-3-5.
To summarize, I usually choose Windows as the authentication mode. It is secure and simple and works for most people in an enterprise environment. If you're creating a new service and for some reason Windows cannot be used, go for Certificate or Password. If you're hooking into an older SOAP service hosted in IIS, you may need to look at using None, Basic or Digest.
Although I asked this question I will add what I know about Certificates as this is something I have worked with - though if my understanding is imperfect, I'd be happy to be corrected.
An X.509 certificate consists of a Public Key and a Private Key and issued by a trusted Certificate Authority (you can self-sign a certificate, this limits the usefulness of the certificate to trusted sources only). The CA will charge a fee for the certificate, and it will expire after a period of time.
The Public Key does not need to be protected and is given to the server. The Private Key is kept private and is used by the client. Messages encrypted by the Private Key can be decrypted by the Public Key.
A request from a client has a digital signature embedded in the SOAP. This is generated using the Private Key. When the server receives the request, it uses the Public Key to read the signature. If the signature can be read, then the request is considered genuine.
Within Active Directory, there is a mechanism whereby an X.509 certificate can be mapped to a user account, so you can impersonate a user with a certain permission set based on the X.509 authentication.
The benefits of X.509, are:
that it can be used across domains; and
that the Private Key can be securely stored in the client's Certificate Store. So there is no .config file containing credentials.
Failure to control the distribution and storage of a Private Key is akin to writing a username/password on a post-it note and sticking it on your monitor.

Categories