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

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.

Related

About proxy man-in-middle attack

I have a website that run under a H2O Proxy, let's call it A server. The backend is WordPress site running with EasyEngine script, let's call it B server.
Now it running like this:
User --(Let's Encrypt SSL)--> A (H2O Proxy) --(self-signed SSL)--> B (nginx backend).
I wonder if attackers know my backend's IP address, so can he decrypt or do harmful thing or see what user send to proxy? And how to setup a better strategy?
I have thought to setup Let's Encrypt SSL from A server to B server too. But I think the problem will occur when Let's Encrypt can only renew certificate on A server because the domain is pointing to A's IP address. And the backend (B server) can't renew it.
Found this answer but I don't really know how to do it: https://serverfault.com/a/735977.
It sounds like what you're trying to do is to put LetsEncrypt into as many places as possible, possibly facing the issues of not having the desired Fully-Qualified-Domain-Name for the applicable backend on the backend itself in order to get the certificate, especially for automated renewal.
But the whole and only purpose of LetsEncrypt is that it gives you certificates that would expectedly be recognised by all the major browsers, such that the users would not have to manually verify and install your certificate into their respective cacert.pem.
But if you just need a secure connection between your own backend and front-end server, then you're not facing the same issue; as such, using LetsEncrypt provides little, if any, extra protections. What you have to do is use something like proxy_ssl_trusted_certificate, together with proxy_ssl_verify, both on the front-end, to pin the backend's certificate and/or certificate authority on the front-end, which will be an order of magnitude more secure (due to the pinning) than using LetsEncrypt on the backend.

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"

configure tomcat for client authentication only for specific URL patterns

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.

Managing SSL certs for a multi-tenant website

We have a multi-tenant website where we use a wildcard SSL cert to give people a subdomain to our site. Some of our customers would like to use their own domain, but I'm concerned about how we would manage each customer's certificate as our business grows. Currently the certificate resides on the web server, which means loading all of the certs to each web server as we add them.
I'm aware we could introduce a dedicated SSL device in front of the web servers, but are there other options to improve the management of these certificates?
I'm a Microsoft Technical Evangelist and one of my partners had exactly the same challenge.
I have created a sample source code that automates and manages SSL certificates for multiple domain bindings using a new IIS 8 (Windows Server 2012) feature called SNI, which is a kind of SSL hostheaders.
All you will need to do is to reuse my code (it's quite simple) and upload your custom SSL certificates to the blob storage, or you can write your own provider to fetch custom domains and certificates from your database.
I have posted a detailed explanation and a sample "plug & play" source-code at:
http://www.vic.ms/microsoft/windows-azure/multiples-ssl-certificates-on-windows-azure-cloud-services/
You could make your clients deal with their own certificates and make them run there own https site. They can serve a page containing a single frame with your content (over https). The users will see their domain and their certificate and the browser will load the frame without complaining as long as the frame contents are also loaded over a valid https connection. I created a quick an dirty test page so you can see it in action.
This solution will 'break' the address bar as it will keep the url of the page containing the frame. Depending on the type of site you're running this might be a showstopper.

SSL - How and when to use it

I have a client that needs SSL to protect online donations, but I have limited experience with how/when to use SSL.
I understand that in purchasing a certificate that I am assigning that certificate to an entire domain (IP address really). Is there a way to isolate the encryption to only a single page of the website, or should I just go ahead and secure the entire site even though only one page needs it?
Unsure of best practice here. Please advise.
SSL incurs quite a bit of extra processing time. For low bandwidth sites, the extra processing required by SSL is not really noticeable. But for sites with heavy traffic like Facebook, Twitter and Flickr, the load caused by SSL is heavy enough that they would have to use dedicated SSL encoding/decoding hardware.
So basically yes, it makes sense to minimize the number of pages using SSL. That is why you often see banking sites only protect the actual account pages via https. The home/landing page is usually plain old http.
On the other hand, unless you really are a site like Twitter or Facebook or Gmail, worrying about this is a bit of a premature optimization. First do it simple if you can. Be aware of this issue and be aware of upgrade strategies when your site finally get heavy traffic.
My boss has a saying:
This is a happy problem to have. First solve the sad problem of
not having enough users then you'd be happy to have a problem that
requires you to refactor your architecture.
You don't encrypt a website with SSL. you encrypt the connection. Therefore if you have SSL enabled for the webserver simply adding https:// to the url will encrypt the connection and whatever page the url points to will be encrypted while in transit.
so
https://www.website.com/index.html is encrypted and http://www.website.com/index.html is NOT encrypted
I prefer for that to never happen so I always put my encrypted pages in a subdomain eg.
https://secure.website.com/index.html
SSL comes with a couple of gotcha's
1/ a basic SSL certificate will only be valid for a specific domain name so if the certificate for is www.website.com and someone follows a link for website.com a warning will be displayed. (see note below)
2/ SSL requires a dedicated IP (which you appear to have). that means you may have problems if you are on a shared platform. this is because in HTTP the host or domain name is part of the headers but the headers are encrypted so the server can't know where to route the request to. (see note below)
It sounds like you really need to employ the services of someone familiar with ecommerce and SSL to help you. navigating the minefield with limited knowledge and forum responses is not the safest thing to do. especially if financial transactions are taking place because there are other requirements that must be considered such as the legal requirements in storing and using financial information such as credit card numbers.
DC
Addendum:
For donations consider Paypal. They have a complete donation solution and more people will trust it than a roll your own solution.
EDIT 2016:
The world moves on and some of the advice above is not as true as it was when originally answered.
SSL no longer requires a dedicated IP address. SNI (Server name indication) resolves that and is almost universal now (IE8 on winXP does not support it and a few phones).
You will find most certificate vendors now include the main domain name as a SAN (subject alternative name) in a certificate. Which is to say they will provide a certificate for both www.website.moc and website.moc if you get a certificate for www.website.moc. Do not assume this, make sure your certification authority specifies it.
also, you mentioned that an SSL certificate protects an IP address. This is incorrect. An SSL certificate corresponds to a domain. Many schemes exist where several domains share a single IP address. If one of these shared domains has an SSL certificate, that certificate is only good for that domain, not the others.
Cookie security is the main thing that I'd point to for your approach.
A user that logs in on your secure login page gets a cookie for their session, right? That cookie's then being transmitted in plain text for someone watching the wire (Firesheep) to intercept and steal the session.
There is additional overhead in terms of negotiation time and CPU load from SSL, but it's rather minimal. If there's anything sensitive going on on your site, just use SSL everywhere.
The other answers are inaccurate in this regard: An SSL certificate binds to BOTH a dedicated IP address that is assigned to a static single domain name, unless you purchase a wild card SSL. Both the domain name and IP must match the certificate.