configure tomcat for client authentication only for specific URL patterns - authentication

I have an application with a few war files all deployed on the same tomcat server. I need to force client authentication only for one war context, and only for a specific URL.
I've read a lot on the web and similar questions here, but the conclusions I've reached are not matching the solution I need:
define 2 connectors with different ports (one with clientAuth enabled and one without) and access the specific URL with the relevant port ==> this solution is not good since if a hacker tries to access this URL with the other port he can succeed
define transport-guarantee in web.xml (for example Enabling mutual SSL per service in Tomcat) ==> this is also not good since I don't want to define users in some realm, I just want the server to ask for the client certificate and verify it is trusted and valid.
Is there a way to use option 2 without defining users? Or maybe a third option?
Thanks in advance!

You can't do this in pure Tomcat. The best solution is to put an Apache HTTP in front of it, that terminates the SSL connection, and in which you can configure SSL to your heart's content right down to the level of an individual directory.

If you want to accept any certificate from trusted CAs, just put clientAuth="want" to Connector and write a filter to check, if a certificate was sent. Assign that filter to desired web app only. In the filter, get the certificate using:
request.getAttribute("javax.servlet.request.X509Certificate");
and check it's CA.
But remember, that any certificate from that CA will allow access. If this is a public CA, anyone can buy one and access your app. You should always check the DN, in Tomcat you do this by defining a user, or manually in a filter.

Related

Apache: How to Block "curl --insecure" in a ssl virtual host

I did create a ssl virtualhost in apache with a self-signed certificate.
In my opinion the configuration is correct however it is possible to access this url using "curl --insecure".
Searching at google, reading several tutorials and trying several configurations (diretives SSLVerifyClient|SSLVerifyDepth|AuthType|AuthBasicProvider|AuthUserFile|Require valid-user) I did not have any success in block this url using "curl --insecure"
I have been thinking in testing mod_security but I don't know if is the right way.
Could you give me some advice?
Thanks
Hudson
I suspect you may need to refine the understanding of sleep. You can't force clients to verify your SSL certificate. Besides, if you're using a self signed cert, it would never verify for anyone who didn't add the cert to their ca library.
You could block curl by rejecting requests based on their User Agent string. But that's just a header, and can be set by the client to anything ( such as a "valid" browser URL). If you really want to control clients, one way would be to use client certificates, which is the analog of the server certificate you set up, but on the client side. In that case, in addition to the client (ostensibly) verifying the server's cert, the server would verify the client's cert, providing a very strong and reliable mechanism to verify client access. Unfortunately, due the the difficulty of generating keys and cert signing requests, and signing certs for clients, client http certificates are not common. But they're very secure, and a good choice if you control both sides.
A middle ground would be to add an authentication layer into your app to control who can access it (you'd then refuse unauthenticated requests altogether)
In short, though, none of these things block curl. They block clients who cannot authenticate. I would recommend you not focus on the remote browser/client in use ( that's at the discretion of your http client). instead, focus on providing the security authentication you require. IMHO, trying to block client user-agents is a fool's errand. It's security by obscurity. Anyone can set any user-agent.

Detect when users deliberately bypass https server certificate errors

Is there a https header on the server, or JavaScript method in the browser, that will let us detect when the user has intentionally bypassed the security certificate, or any other way to detect and report this kind of situation? (We are using Linux / Apache / jQuery.)
The Web is filled with ways to routinely skip the warning, but I haven't been able to find a single thing about detecting when users skip it - just the horrifying statistic that 70% of users bypass the warning as quick as they can. (How do they measure that?)
We operate a web application that lets teachers make and administer tests. Teachers are connecting to unauthorized WiFi networks, getting invalid certificate warnings, and clicking on the browser's "accept anyway" feature so they can get to our application despite having certificate that is not authenticated. We want to understand how often this happens, and who is doing it, and progress to stopping it.
I should note that there are schools that proxy requests through their own server, with their own certificate, and we are OK with this - it's the "ignore and connect anyway" connections that we want to measure and mitigate, because those are the ones that students are setting up, without access to their own CA but ample access to lazy users.
One way to make sure that the client has seen the server certificate you sent is to use client-certificate authentication. One of the last steps of the SSL/TLS handshake when using client-certificate authentication consists of a hash of all the handshake messages signed with the client's private key.
A side effect of this is that, if the client didn't see the exact same server certificate, the server wouldn't be able to validate this signed hash coming from the client.
This certainly doesn't necessarily mean that the client checked the certificate as it should have (i.e. whether the certificate was trusted and belonged to the server the client intended to contact), but at least the server has a way there was no fake cert in the middle.
HSTS (which you mention) also has a way to make the client enforce these checks (see Section 8.4 of RFC 6797). However, it only works if the client already knows HSTS needs to be used (either as a pre-loaded host, or after a first visit), and of course relies on the client supporting HSTS (browser support is still limited).
Not sure what you mean by bypassing HTTPS. If you mean they can visit your URI without HTTPS, that means you need to block HTTP access in Apache's .htaccess, httpd.conf, or default-ssl config files. Broken padlock could mean a number of different things so it's not clear which problem you're having. You can test your site for SSL security problems here:
https://www.ssllabs.com/ssltest/
Edit:
You can compare the fingerprint of the SSL certificate on the server and on the client to make sure they match (if the client is able to get the fingerprint). That should prevent man-in-the-middle attacks with bogus certificates.
Article
and here's an answer for doing this on the server side of things. It sounds like the best way to avoid interception is to authenticate the client with their own certificate.
There is no way to detect this - the user is the only one who can see if the padlock is green and locked or red and broken.
Firefox will do this by extension and through xhtml, but it is, as of now, the only browser to support this.
I was looking for HSTS. Here is how it works and how to implement it.
TL;DR: Header add Strict-Transport-Security "max-age=15768000 includeSubDomains"

How to implement a SSL Client Certificate on an Apache Server for a REST api?

Background:
Imagine a website, visible to the world, https://www.example.com, with a static IP address, 1.1.1.1. This site is hosted in an Apache server and it already possess an SSL Server Certificate.
On the other hand, inside a protected internal network, not visible to the world, a server (https://www.myinternalserver.com), with a static IP address (2.2.2.2), also running Apache, runs some internal web-based applications.
A static IP address (3.3.3.3), that maps to a subdomain (myapps) of the external site (https://myapps.example.com) serves as an entry point to the server where the internal web-based applications reside.
A firewall that protects the internal network does the redirect/proxying so all external traffic going to 3.3.3.3 is redirected internally to 2.2.2.2.
The firewall also limits all external traffic so any calls going to 3.3.3.3 must have been originated at 1.1.1.1, in essence, making the external website (https://www.example.com) the only authorized caller to the internal server (https://www.myinternalserver.com).
Scenario
With this infrastructure in place, I can make REST calls from the external website into the internal network and send back data to use in the pages. So, in this scenario, the external site is the client and the internal application, the server.
Question:
But beyond that, I want the server in the internal network to issue an "SSL Client Certificate" that would be "installed" (I don't know if this is the correct term), in the external website so all calls from the external site would have to be authenticated against this certificate.
How do I accomplish this?
Breaking the question:
I know that the question above is very broad, so let me try to break it into three (not so) "smaller" questions:
1 - How to I create the key/certificate? Using OPENSSL and some online recipes (this is one of them: http://www.impetus.us/~rjmooney/projects/misc/clientcertauth.html), I was able to generate the certificate file and learned (or so I believe) what I have to do with it and what to change in the httpd.conf file. In any case, I would like to feel more secure about what I have done so any suggestions/guidance here would be highly appreciated. For example, is the recipe I used any good?
2 - How to "install/transfer" this certificate to the external site? Do I simply copy/send one of the files created when generating the certificate? If so, which one? Where specifically does it go in the client server (external site)? Do they have to do anything at their end? If not, what is the process? I tried to contact the hosting company but I don't know if Icouldn't explain it to them or if they don't have experience with "SSL Client Certificate". All they told me is that there's already an SSL Certificate installed (SSL Server Certificate). They don't even seem to know what a "SSL Client Certificate" is.
3 - Once the certificate in place, what can I do to guarantee that ALL calls to the internal server, by default, come with the Certificate, without the need to code it into each API I create? I know very little about certificates so it might be possible that it happens "by default" always, but I read online about certificates that are "embedded" in the header of the API call, so I just want to be sure.
Thank you.
After some more research, this is what I found...
1 - How do I create the key/certificate?
I had to try other recipes and use a combination of them to get what I wanted. What I learned is that I have to create a certificate (CA Certificate) first, and generate the Server and Client certificates based on that first one. So look for recipes that encompass all three certificates: CA, Server, Client.
2 - How to install/transfer this certificate to the external site?
Actually you simply copy the necessary ones (client/CA) to a safe place in your share of the external site. A place outside the "www" tree.
3 - Once the certificate in place, what can I do to guarantee that ALL calls...
Well, here is what I did.
I "objectified my API call using php/libcURL and place it too, outside the "www" tree. For any developer in my site to use it, all they have to do is create an instance of the object and make the call by passing the URL as a parameter. In other words, you don't install the certificate. Instead, you make a call to the certificates each time you make a call to the internal server.
I hope it helps someone out there.

How to access localhost via https with a valid certificate

We have a Web-Application that should interact with a desktop application that has a helper tool character (e.g. no setup, no need for admin privileges). The helper is listening via http/https on a simple port bound to localhost.
The Web-Application uses a SSL certificate. Every customer has a machine on its own for his data. For claryfication: The Web-Application is running on a server, serving one customer but multiple people.
The problem is, the Web-Application cannot reach the helper tool via https (using image or iframe). The main issue is, that the local webserver listening on localhost has no signed certificate. So the web browser is blocking the interaction.
Is there any way to get around this trouble? I think, I cannot get a certificate for localhost, because no one would sign it.
I know, that I cannot use XMLHttpRequest for this, but that's not the point.
The goal is to have a customer friendly - no install - just works - solution. The customer should not do ANY configuration. Just downloading and starting the tool. We'd like to have a direct communication to the tool (e.g. no outbound direction to the web server).
Is the any solution for this?
If it is Active-directory environment , you can create your own CA and sign certificates and distribute them across the domain. also you can add to trusted sites through domain policies this way client side you don't need to configure anything .

Azure app using custom domain with SSL certificate

Could someone explain the steps that one must do to show an Azure application (example.cloudapp.net) in a custom domain (service.example.com), when we want to use a secured connection? So the users browse to https://service.example.com, see it as a certified, trusted domain, and can safely access the application.
Right now, I think that
1) we need a domain (and subdomain) with a static IP from a service provider
2) we need a certificate from a CA for our domain
But I'm not quite sure how the connection between our domain and cloudapp.net should be made. I have found many examples and blog posts, but they tell either how to install a certificate to Azure application or how to show the application in custom domain (without the certificate).
This sounds like a basic requirement, so I'd expect a rather simple solution to exist.
Thanks!
Look at this blog entry
Custom Domain Names in Windows Azure
Basically you need to buy domain name and add some CNAME record in DNS table. The part remaining would be to buy appropriate SSL certificate for your site.
Here is a stop-gap for custom domains: http://www.bradygaster.com/running-ssl-with-windows-azure-web-sites
I do not believe that Azure currently supports using a certificate with a custom domain (see request for feature). In the meantime, you can use CORS.