Why does Chrome hate self-signed certificates so much? - amazon-web-services

I'm running a small web app on an EC2 instance and I want some friends to be able to use it. I also want to make it use HTTPS, just for basic security purposes (prevent packet snooping whenever possible). Of course I am using a self-signed certificate, because my budget for this project is $0. But Chrome throws up a warning page upon trying to visit it:
Your connection is not private
Attackers might be trying to steal your information from [...]
(for example, passwords, messages, or credit cards).
NET::ERR_CERT_AUTHORITY_INVALID
This server could not prove that it is [...]; its security certificate is not trusted by your computer's operating system. This may be caused by a misconfiguration or an attacker intercepting your connection.
Is is not true that "any encryption is better than no encryption"? On unenecrypted HTTP, I could be trying to steal information as well, and don't have to prove anything about my server identity, AND my communication can be read in plaintext by packet sniffing, but Chrome doesn't throw up any warning flags there...
What gives? Why does Chrome hate self-signed certificates so much? Why doesn't it just put a little red box over the padlock icon, instead of giving me a two-click warning page?
Edit Sep 2021 (this was applicable since 2016): Just suck it up and use one of the free key issuers. Let's Encrypt and AWS ACM will literally do it for free.

This question is not specific to chrome. Firefox and probably other browsers behave similar and in the last years the warnings even got stricter. Complaining about these warnings shows more a missing understanding of the role of certificates in HTTPS.
With HTTPS one expects encryption, i.e. private communication between the browser and the server with nobody sniffing or manipulating the transferred data. At the beginning of the encryption client and server exchange the encryption keys, so that one can encrypt the data and the other can decrypt the data. If some man-in-the-middle manages to manipulate the key exchange in a way that it gets control over the encryption keys, then the connection will still be encrypted but not private. Thus it is essential that the key exchange is protected and this is done with certificates. Only with proper checking of the certificates the client can verify that it talks to the server and not some man-in-the-middle and thus the critical key exchange can be protected.
Certificates are usually verified by
Checking the trust chain, i.e. if the certificate is directly or indirectly (via immediate certificates) issued by a certificate agency (CA) trusted by the browser or operating system.
Verifying that the certificate is issued for the expected hostname, i.e. the subject matches the hostname.
With self-signed certificates or certificates issued by a CA unknown to the browser/OS this check will fail. In this case it is unknown, if the original certificate was already not issued by a trusted CA or if there is some man-in-the-middle manipulating the connection. Being man-in-the-middle is not hard, especially in unprotected networks like public hotspots.
Because the browser can not verify the certificate in this cases it will throw a big fat warning to show the user that something is seriously wrong. If your friends know that you only have some self-signed certificate there they should also know that this is the expected behavior of the browser in this case. You also should provide them with the fingerprint of your certificate so that they can be sure that this is the expected certificate - because there is no other way to check the validity of this certificate. Note that this warning also comes once because the browser saves the fingerprint and from then on knows that your site is associated with this certificate. But if you change the certificate it will complain again.
If you don't like the trouble of teaching all of your friends how to properly verify your certificate then get yourself a certificate by a public CA. They don't need to be expensive and some also issue free certificates.
Is is not true that "any encryption is better than no encryption"?
While bad encryption might be better than no encryption, transferring sensitive data over en encrypted but man-in-the-middle connection is definitely worse then transferring non-sensitive data with no encryption. And contrary to plain HTTP you can actually detect a potential man-in-the-middle attack with HTTPS. What you can not do is find out if this a potential man-in-the-middle attack or if the non-verifiable certificate is actually the expected, because the browser has no previous knowledge what to expect. Thus a self-signed certificate is actually not that bad provided that the browser knows up-front that this site only provides a self-signed certificate. And it might also not bad if the transferred data are not sensitive. But how should the browser know what kind of data and what kind of certificate are to expect?

Because SSL/TLS are trying to solve two problems in a single stroke, but you are completely ignoring one of them.
SSL is meant to provide both encryption (between two endpoints) and authentication (where each endpoint is exactly who it says it is). This latter solution is generally meant to be solved via organizations known as Certificate Authorities (CAs), who are supposed to verify your identity before agreeing to give you a certificate. While there have been some spectacular failures of this level of trust in the past, we don't have anything better yet, and so browsers still expect to see SSL/TLS certificates to be issued by one of these Trusted authorities; if it's not, there's no way to know if you're actually talking to the party you intended to.
So, while it may be encrypted, having an encrypted conversation with someone who shouldn't be party to the conversation is actually WORSE than having a plaintext conversation with someone who SHOULD be party to the conversation.
There are a few free SSL providers out there such as Let's Encrypt that won't cause this warning and still fit in your $0 budget.

Put chrome://flags/#allow-insecure-localhost into the Chrome address bar, then select the enabled option.

The reason for the click through is to offer some protection from phishing attacks.
The $0 work-around is to create a certification authority verified by Justaskin_ (which is just a special file) and have your friends to install the public key derived from of it on their computers.
Instead, use the private key to sign your https certificate and their browsers will accept it. OpenSSL is one tool that can do this.

Related

Certificate expiration and SHA-1

Background: I'm a complete newbie when it comes to certificates.
We have a site running at https://global.projacked.com
The certificate is issued by AWS.
All works well for most of our customers but...
One of them is experiencing the following:
And when I click on "view certificate" I see:
So the question is: can we do anything on our end to make this work?
If not: what can I tell my customer to do to make it work? Is it a question of them updating their certificate? Or might it be cause by them being in a secured network (e.g. VPN)?
Thank you immensely in advance for your help
Your site global.projacked.com is serving a valid SHA-256 certificate. The customer who has reported this issue appears to be having its HTTPS traffic intercepted and inspected by some sort of a MITM software or device (the Issuer -- apotex-CA -- on the certificate they're seeing gives it away). The MITMing entity is generating a certificate that is trusted by the customer's browser but it happens to be a SHA-1 certificate causing Chrome to complain.
You cannot do anything to fix their issue. A lot of MITM software vendors have released updates that create SHA-256 certificates to avoid situations such as this. They can probably check to see if there are updates they can install that generate SHA-256 certificates or read this or this to see if they really need to have TLS traffic intercepted and inspected. Sadly, I've seen organizations where the "solution" to this issue is to install an older version of Chrome that did not care about SHA-1 certificates and disable auto-update. After all, burying your head in the sand is very good at blocking all the noise about this little thing called security.
The certificate issuer should be able to issue a certificate under SHA-256. You'll then need to replace the certificate on the server.
Some certificate authorities can give you new cert as a re-issue of the old one, some will require CSR (Certificate Signing Request) that can be constructed based on the existing private key, which likely resides on the server too.

Is there a way to force browser to accept self-signed certificate using websocket++?

I am using echo_server_tls example with Chrome client. It works fine when I add the certificate to "Trusted Root Certificate Authorities" in certmgr. But if the certificate is not added there, the connection fails silently.
How can I ask user to accept my certificate in case of "Certificate Authority" error?
My OS is Windows 7
You can't do anything once the certificate error is encountered... it's a security feature. What you can do, however, is instruct users before they attempt to use your server that they must install your root certificate. One possible solution is to have them go to an "insecure" (unencrypted) site where the instructions are, then proceed to the "secure" site.
As a side note, buying a real "signed-by-well-known-authority" certificate is not difficult nor expensive... the cost is far less then the trouble of dealing with self-signed certificates in nearly all scenarios.
OK, solved the problem by setting an http handler using set_http_handler().
Thanks

Boost ASIO with OpenSSL Can't Read HTTP Headers

I'm attempting to write a simple HTTP/HTTPS proxy using Boost ASIO. HTTP is working fine, but I'm having some issues with HTTPS. For the record this is a local proxy. Anyway so here is an example of how a transaction works with my setup.
Browser asks for Google.com
I lie to the browser and tell it to go to 127.0.0.1:443
Browser socket connects to my local server on 443I attempt to read the headers so I can do a real host lookup and open a second upstream socket so I can simply forward out the requests.
This is where things fail immediately. When I try to print out the headers of the incoming socket, it appears that they are already encrypted by the browser making the request. I thought at first that perhaps the jumbled console output was just that the headers were compressed, but after some thorough testing this is not the case.
So I'm wondering if anyone can point me in the right direction, perhaps to some reading material where I can better understand what is happening here. Why are the headers immediately encrypted before the connection to the "server" (my proxy) even completes and has a chance to communicate with the client? Is it a temp key? Do I need to ignore the initial headers and send some command back telling the client what temporary key to use or not to compress/encrypt at all? Thanks so much in advance for any help, I've been stuck on this for a while.
HTTPS passes all HTTP traffic, headers and all, over a secure SSL connection. This is by design to prevent exactly what you're trying to do which is essentially a man-in-the-middle attack. In order to succeed, you'll have to come up with a way to defeat SSL security.
One way to do this is to provide an SSL certificate that the browser will accept. There are a couple common reasons the browser complains about a certificate: (1) the certificate is not signed by an authority that the browser trusts and (2) the certificate common name (CN) does not match the URL host.
As long as you control the browser environment then (1) is easily fixed by creating your own certificate authority (CA) and installing its certificate as trusted in your operating system and/or browser. Then in your proxy you supply a certificate signed by your CA. You're basically telling the browser that it's okay to trust certificates that your proxy provides.
(2) will be more difficult because you have to supply the certificate with the correct CN before you can read the HTTP headers to determine the host the browser was trying to reach. Furthermore, unless you already know the hosts that might be requested you will have to generate (and sign) a matching certificate dynamically. Perhaps you could use a pool of IP addresses for your proxy and coordinate with your spoofing DNS service so that you know which certificate should be presented on which connection.
Generally HTTPS proxies are not a good idea. I would discourage it because you'll really be working against the grain of browser security.
I liked this book as a SSL/TLS reference. You can use a tool like OpenSSL to create and sign your own certificates.

Building a secure web service without buying (and renewing) a certificate

The goal: a web service, secure, that will be called by exactly two clients, both outside the local network. The most obvious way to secure a web service is via https, obtaining a certificate from some CA. The problem is that this is a silly waste of money. The whole point of a CA is that it is a publicly trusted authority, so I don't have to verify my identity to every single person who wants to use my web page, the CA is doing that for them. However, when I'm dealing with a very small number of known clients, rather than the wide open public, I don't need anyone to vouch for me. We can do verification through our own channels.
Is there any way to accomplish this? Ideally, I'd be able to operate https with a certificate recognized by those calling my service, and if nobody else recognizes the certificate as valid, I don't care. I don't want them calling this service anyway. This should be a fairly common need in B2B data transfers (fixed-endpoint communications, rather than services intended for public consumption), and it is easy to do if you're transferring actual files (PGP-style encryption lets you simply verify and import one another's keys directly). But it isn't clear to me that this is possible with web sessions. It sure should be, if it is not. I have found some documentation of self-signed certificates, but they all seem to be intended for development purposes only, or internal use only, and expire quickly or require being on the same network.
Is there a good way to achieve this? Or am I going to have to encrypt the contents of the web service call instead? The latter is less desirable, because it would require the users of this service to add encryption code to their client applications (which assumes they are building these on a platform which easily can add support for common encryption routines, something that may or may not be true) rather than just relying on the standard, https framework.
I'm working on the Windows (IIS/ASP.NET) platform, if that makes any difference.
Creating your own CA and generating self-signed certificates is the way to go. There is no reason why they must be for development only, or expire quickly. You will be in control of this.
When I implemented this in a Java environment, the most useful resource I found was on Baban's Weblog. You can probably find a resource more relevant to your IIS environment.
To offer a secure service you don't need any certificate, only an https link. You are right that, in your case, a certificate does nothing for you. If your visitor insists on a certificate, then I second #sudocode's answer.
Our old authorization service used certificates, but in rebuilding it we got rid of the certificates and went to an Amazon ec2 style security for the services.

Any real downside to using self-issued certs when dealing with known agents?

I'm setting up a web service which will only be used by a limited number (< 100) of known agents (business partners etc.).
Because I am not public facing, do I face any real downside to using self-issued certs as opposed to the much more costly route of using a known CA?
Edit: I should clarify that the primary purpose we hope to get out of the certificates is to fulfil the 2nd factor in two-factor authentication (password for what-you-know, X.509 cert for what-you-have)
There's no real downside, but it's easier to use a private CA in those circumstances. That private CA has a self-signed certificate, and authorizes everything else in your closed world. Write down a policy (you know, on a piece of paper) for who gets their certificate signed and how you go about doing the signing, and you'll be operating like the “real” CAs do.
But if there are external business partners involved, it's probably easier to just use a normal CA. You can get your service certificates signed for very little so cheap-skating on them is just not really worth it. It only becomes a hassle when you start to want to do things like delegated authority and things like that; at that point, you want to start reading about OAuth and FOAF+SSL. And maybe other things too; it's a deep rabbit-hole.
With a self-signed cert, the users will be warned that the certificate is not trusted by the browser until they manually add the signing certificate into their certificate cache, or will have to click to accept the fact that the certificate may be untrusted.
With a known CA such as Verisign, the signing certificate will typically already be preinstalled on their PC, so the user will receive no prompt
Also a security consideration (from Wikipedia - haven't encountered this myself): "Self-signed certificates cannot (by nature) be revoked, which may allow an attacker who has already gained access to monitor and inject data into a connection to spoof an identity if a private key has been compromised. CAs on the other hand have the ability to revoke a compromised certificate, which prevents its further use."
I would think most security-conscious people would hesitate to import some guy's root certificate. Heck, i have certificates i've generated MYSELF that i don't want to import. And a lot of software will refuse to deal with a server whose cert isn't issued by a CA it (or the OS) trusts.
Seriously, check out http://www.startssl.com. They offer free certificates, which appear to be pretty well supported by most common browsers and OSes. It's a lot easier than even trying to tell people how to install your root cert.