NET::ERR_CERT_COMMON_NAME_INVALID with Cloud front - amazon-cloudfront

I have an S3-hosted static website and a Cloud Front distribution. THere is an A record in Route 53 pointing to the Cloud Front distribution. When I created the distribution, I accepted the default setting for the certificate. That is, I did not enter a certificate ID or request a certificate. When I attempt to browse to the site with Chrome, I get NET::ERR_CERT_COMMON_NAME_INVALID.
How can I view or modify the common name of the default certificate? It doesn't appear in Certificate Manager.

This is not programming or development and may need to be deleted but:
to answer as asked:
For most builds of curl (but not the Microsoft-supplied curl.exe on Windows, which uses schannel) curl -v https://host will display the subject and some other attributes of the (server/leaf) cert; the CN= part is the CommonName. Pretty much all Linux and most other Unix will have suitable curl preinstalled; on Windows you can either find and install a non-schannel build for Windows (which may not be so easy as it was when I was younger), or use WSL (which gives you a Linux build).
If you have OpenSSL, echo Q | openssl s_client -connect host:443 (for versions below 1.1.1 you may need to add -servername host) will show the subject and issuer names of all certs in the chain (as validated, which may differ from sent in the CA(s) but not the leaf); you want the '0 s:' line, or the repeated info at Server certificate / subject= a page or two down. Again nearly all Linuxes and Unixes have OpenSSL; for Windows you can get a port from http://www.slproweb.com/products/Win32OpenSSL.html or again use WSL. (Instead of echo Q | you can use </dev/null on Unix or <NUL on Windows.)
If you have Java, keytool -printcert -sslserver host shows a lot of info about the cert chain; the first lines Certificate #0 / ===== / Owner: are the ones you want. 15 or 20 years ago when Java was considered the wave of the future it was available almost everywhere; today not so much. I wouldn't install Java just for this, but if you want it for any better reason(s), go for it.
but you don't want to.
That error code in Chrome is very misleading. Decades ago it was the standard or at least usual convention to use (and verify) CommonName in Subject to be the server hostname. Since about 2010 all public CAs, and most others as well, switched to using the SubjectAlternativeName aka SAN extension instead. Initially browsers continued to accept CommonName if SAN is absent, but since about 2017 Chrome only uses SAN and never ever looks at CommonName. So that error code now actually means SAN doesn't match or is missing; CommonName may well be correct, and even if it is wrong fixing it won't fix the Chrome error.
so how do you fix SAN in CloudFront? I can't help there.

There is a setting in Cloud Front where you can put in the SAN - it's called "alternate domain name."
I had to examine the certificate to see that it didn't have mydomain.com as an alternate name - all it had was the domain name of the cloud front distribution.

Related

CouchDB 3.1 Installer - unknown publisher

I have just gone to https://couchdb.apache.org/ to get the latest CouchDB binary (upgrading from 2.2).
However, the download link redirects me to an organisation called Neighbourhoodie - a CouchDB services & consultancy firm (which was unexpected, but understandable as I know the installations may be served from mirrors).
When I ran the installer I got a warning from Windows that the binary is from an 'Unknown Publisher'.
I can't find a contact point on the CouchDB site to ask a question like this.
The unexpected redirect coupled with the Unknown Publisher have made me nervous - how can I know that it's safe to proceed with the upgrade?
You can verify that the couchdb contributors that signs public releases believed this binary is correct for windows users by comparing the site, sha1 and md5 sums they gave in an issue. Neither a sha1 or md5 alone is secure, but I think it would be exceedingly hard to find an attack that simultaneously works for both.
Also, if you download the gpg signature, binary and the https://downloads.apache.org/couchdb/KEYS you can verify that this signer is the same signer using the same key recognized on the apache download site. Using their trust is similar to tofu, you trust the channel with https and it trusts this key, so now you trust the key on another channel.
On linux/mac this looks like:
(verify you obtain keys over ssl from apache, then:)
$ gpg --import KEYS.txt
...
gpg: key CDE711289384AE37: "**** (CODE SIGNING KEY) <****#apache.org>"
(download a sig and file from official downloads.apache.org site and verify + add your "tofu" trust in this key)
$ gpg --trusted-key CDE711289384AE37 --verify apache-couchdb-3.1.1.tar.gz.asc
(your gpg now trusts this key for new binaries)
$ gpg --verify apache-couchdb-3.1.0.msi.asc
(If the official KEYS file changes you would want to delete this trust and do the same process again:)
$ gpg --delete-key CDE711289384AE37
and windows gpg should look similar, maybe with / in place of --, etc.

IIS TLS Certificate - Chrome says we are using "obsolete cryptography"

We have installed a server certificate in IIS for a website. When browsing over HTTPS to the website and inspecting the icon using chrome, we get a message "Your connection ... is encrypted with obsolete cryptography".
How do I configure IIS so that Chrome stops displaying this message, also need to balance the need to support IE>=8.
[EDIT]: As per the screenshot, we can see that the encryption method used is "AES_256_CBC with SHA1 for message authentication". The question is how do we change this in IIS so that Chrome no longer complains about "Obselete Cryptography".
The answer Steffen gave is incorrect (although the link he provided does provide the answer if you read further down). The reason Chrome gives the error regarding obsolete cryptography in this case is due to AES in CBC mode.
It has nothing to do with having a SHA-1 certificate.
The TL;DR - ignore this error, it doesn't matter.
If you really want to get rid of the error then you need to enable AES GCM instead. However this is easier said than done. I answered this in full on serverfault recently - see the second half of my answer here;
https://serverfault.com/questions/683697/change-key-exchange-mechanism-in-iis-8/683705#683705
Since am new to SSL and certificates, I struggled with this too. Here's how we solved this issue. Note that in our case, we are working with an internal web application and use a self-signed certificate.
Using OpenSSL on Linux, create a private key:
openssl genrsa -out box.key 2048
Then create and sign a certificate with the key (we set the expire date for a year out and 10 days):
openssl req -new -x509 -sha256 -days 375 -key box.key -out box.crt
Answer the questions (make sure the Common Name matches the web server's FQDN)
Configure your web server to use SSL using this key and certificate
Using Chrome on Windows, enter your web sites HTTPS URL
Click on the lock icon in the address bar, then select the Certificate Information link in the popup
Go to the Details tab, select the Copy to File... button to launch the Certificate Export Wizard
Using the wizard, select PKCS #7 as the export format, and save the certificate (i.e. mykey.p7b)
Install the certificate in the Trusted Root Certification Authorities certificate store (use certmgr.msc or right click on the certificate and select Install Certificate
Close Chrome, logout and re-login to Windows (force the old site warning out of the cache)
Re-open Chrome and enter your web sites HTTPS URL
Admire your shiny green lock icon with modern cryptography
You might want to read https://www.chromium.org/Home/chromium-security/education/tls#TOC-Deprecation-of-TLS-Features-Algorithms-in-Chrome, which was the first hit when looking for this specific error message.
It is hard to know for sure without having a look at your certificate, but I guess the following description from the linked page will match your certificate:
SHA-1 is deprecated in Chrome at the start of 2015.
Certificates expiring in 2016 will be marked as "secure, but with minor errors".
Certificates expiring in 2017 are later will be treated as "affirmatively insecure".
To answer my own question:
Ensure latest Windows Updates have been installed
Download and run IIS Crypto (https://www.nartac.com/Products/IISCrypto)
Ensure that this Cipher is top of the list on the left hand side:
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
Apply changes in IIS Crypto
Restart the server
In this link there are a black and a white lists about ciphers. Maybe if you just use the white ones it would solve your problem. Look after the lists in the comments you will see that it has change a little since the answer was written.
It helped me a lot when I started to have this problem with Glassfish, I hope it helps you with IIS too.

How can you test that an SSL client library is properly verifying the certificate of the server to which it connects?

I want to ensure that client libraries (currently in Python, Ruby, PHP, Java, and .NET) are configured correctly and failing appropriately when SSL certificates are invalid. Shmatikov's paper, The Most Dangerous Code in the World:
Validating SSL Certiļ¬cates in Non-Browser Software, reveals how confusing SSL validation is so I want to thoroughly test the possible failures.
Based on research a certificate is invalid if:
It is used before its activation date
It is used after its expiry date
It has been revoked
Certificate hostnames don't match the site hostname
Certificate chain does not contain a trusted certificate authority
Ideally, I think I would have one test case for each of the invalid cases. To that end I am currently testing an HTTP site accessed over HTTPS, which leads to a failure that I can verify in a test like so:
self.assertRaises(SSLHandshakeError, lambda: api.call_to_unmatched_hostname())
This is incomplete (only covering one case) and potentially wrong, so...
How can you test that non-browser software properly validates SSL certificates?
First off, you'll need a collection of SSL certificates, where each has just one thing wrong with it. You can generate these using the openssl command line tool. Of course, you can't sign them with a trusted root CA. You will need to use your own CA. To make this validate correctly, you'll need to install your CA certificate in the client libraries. You can do this in Java, for example, using the control panel.
Once you have the certificates, you can use the "openssl s_server" tool to serve an SSL socket using each one. I suggest you put one certificate on each port.
You now have to use the client library to connect to a port, and verify that you get the correct error message.
I know that Python by default does no certificate validation (look at the manual for httplib.HTTPSConnection). However, m2crypto does do validation. Java by default does do validation. I don't know about other languages.
Some other cases you could test:
1) Wildcard host names.
2) Certificate chaining. I know there was a bug in old browsers where if you had a certificate A signed by the root, A could then sign B, and B would appear valid. SSL is supposed to stop this by having flags on certificates, and A would not have the "can sign" flag. However, this was not verified in some old browsers.
Good luck! I'd be interested to hear how you get on.
Paul
Certificate hostnames don't match the site hostname
This is probably the easiest to check, and failure (to fail) there is certainly a good indication that something is wrong. Most certificates for well-known services only use host names for their identity, not IP addresses. If, instead of asking for https://www.google.com/, you ask for https://173.194.67.99/ (for example) and it works, there's something wrong.
For the other ones, you may want to generate your own test CA.
Certificate chain does not contain a trusted certificate authority
You can generate a test certificate using your test CA (or a self-signed certificate), but let the default system CA list be used for the verification. Your test client should fail to verify that certificate.
It is used before its activation date, It is used after its expiry date
You can generate test certificates using your test CA, with notBefore/notAfter dates that make the current date invalid. Then, use your test CA as a trusted CA for the verification: your test client should fail to validate the certificate because of the dates.
It has been revoked
This one is probably the hardest to set up, depending on how revocation is published. Again, generate some test certificates that you've revoked immediately, using your own test CA.
Some tools expect to be configured with a set of CRL files next to the set of trusted CAs. This requires some setup for the test itself, but very little online setup: this is probably the easiest. You can also set up a local online revocation repository, e.g. using CRL distribution points or OCSP.
PKI testing can be more complex than that more generally. A full test suite would require a fairly good understanding of the specifications (RFC 5280). Indeed, you may need to check the dates for all intermediate certificates, as well as various attributes for each certificate in the chain (e.g. key usage, basic constraints, ...).
In general, client libraries separate the verification process into two operations: verifying that the certificate is trusted (the PKI part) and verifying that it was issued to the entity you want to connect to (the host name verification part). This is certainly due to the fact these are specified in different documents (RFC 3280/5280 and RFC 2818/6125, respectively).
From a practical point of view, the first two points to check when using an SSL library are:
What happens when you connect to a known host, but with a different identifier for which the certificate isn't valid (such as its IP address instead of the host)?
What happens when you connect to a certificate that you know cannot be verified by any default set of trusted anchors (for example, a self-signed certificate or from your own CA).
Failure to connect/verify should happen in both cases. If it all works, short of implementing a full PKI test suite (which require a certain expertise), it's often the case that you need to check the documentation of that SSL library to see how these verifications can be turned on.
Bugs aside, a fair number of problems mentioned in this paper are due to the fact that some library implementations have made the assumption that it was up to their users to know what they were doing, whereas most of their users seem to have made the assumption that the library was doing the right thing by default. (In fact, even when the library is doing the right thing by default, there is certainly no shortage of programmers who just want to get rid of the error message, even if it makes their application insecure.)
I would seem fair to say that making sure the verification features are turned on would be sufficient in most cases.
As for the status of a few existing implementations:
Python: there was a change between Python 2.x and Python 3.x. The ssl module of Python 3.2 has a match_hostname method that Python 2.7 doesn't have. urllib.request.urlopen in Python 3.2 also has an option to configure CA files, which its Python 2.7 equivalent doesn't have. (This being said, if it's not set, verification won't occur. I'm not sure about the host name verification.)
Java: verification is turned on by default for both PKI and host name for HttpsUrlConnection, but not for the host name when using SSLSocket directly, unless you're using Java 7 and you've configure its SSLParameters using setEndpointIdentificationAlgorithm("HTTPS") (for example).
PHP: as far as I'm aware, fopen("https://.../") won't perform any verification at all.

Determining if a TLS/SSL certificate is 'trusted' from the command line?

I would like to be able to determine if a remote domain's TLS/SSL certificate is 'trusted' from the command line.
Here is an openssl example I was playing with a few weeks back, here I use openssl to acquire the certificate and then pipe it to openssl's 'verify' command. I assumed that the 'verify' command would verify the certificate, however, how I understand it now is that the 'verify' command just verifies the certificate chain (I think). (cdn.pubnub.com is just a domain I found from a quick Twitter search as an example to use)
echo "GET /" | openssl s_client -connect cdn.pubnub.com:443 | openssl x509 -text | openssl verify
As you can see from the cdn.pubnub.com domain (at the time of writing), the browser (Chrome at least) does not trust the certificate (because the certificate domain doesn't match), however, the openssl 'verify' command does not output 'trusted' or 'not trusted' or something else we can deduct that information from.
Another way I thought of doing this, is by using a headless browser (such as PhantomJS) and parsing any errors they return. It turns out that PhantomJS just errors but does not give any details, so this can not be used as the error could have been caused by something else.
I didn't think it would be this hard to find out that a certificate was trusted or not from the command line, without having to parse and check all the data that makes a certificate trusted myself which I don't think would be wise.
Is there a library or some other way I can tell if a remote domain's certificate is trusted from the command line?
curl (and libcurl) uses OpenSSL for https URLs, and checks certificate validity unless -k, --insecure option is enabled.
zsh 29354 % curl https://cdn.pubnub.com/
curl: (51) SSL peer certificate or SSH remote key was not OK
As you see, it doesn't give much details on why the certificate is invalid, but otherwise it should be as good as a headless browser, and much lighter.
It depends on what you consider "trusted". Beside the core cryptographic checks (e.g. checking the digital signature) the client usually does the following:
Check that the certificate chains to a trusted root
Verify that the current time is between the notValidBefore and not validAfter attributes.
The certificate is not revoked.
keyUsage and other certificate constraints match.
The entity we are communicating is somehow found in the subject of the certificate (for servers this usually means the hostname is listed as CN or subjectAlternativeName).
In your case the information to verify step 5 (namely the hostname) is missing, so it cannot be checked. You would have to do this step yourself.
Please note that different clients perform different checks to see if a certificate is trusted, so one answer may not apply to all possible clients. If you want to check your installation deeply, consider using the check from ssl labs https://www.ssllabs.com/ssltest /

Advanced SSL: Intermediate Certificate Authority and deploying embedded boxes

Ok Advanced SSL gals and guys - I'll be adding a bounty to this after the two-day period as I think it's a complex subject that deserves a reward for anyone who thoughtfully answers.
Some of the assumptions here are simply that: assumptions, or more precisely hopeful guesses. Consider this a brain-teaser, simply saying 'This isn't possible' is missing the point.
Alternative and partial solutions are welcome, personal experience if you've done something 'similar'. I want to learn something from this even if my entire plan is flawed.
Here's the scenario:
I'm developing on an embedded Linux system and want its web server to be able to serve out-of-the-box, no-hassle SSL. Here's the design criteria I'm aiming for:
Must Haves:
I can't have the user add my homegrown CA certificate to their browser
I can't have the user add a statically generated (at mfg time) self-signed certificate to their browser
I can't have the user add a dynamically generated (at boot time) self-signed certificate to their browser.
I can't default to HTTP and have an enable/disable toggle for SSL. It must be SSL.
Both the embedded box and the web browser client may or may not have internet access so must be assumed to function correctly without internet access. The only root CAs we can rely on are the ones shipped with operating system or the browser. Lets pretend that that list is 'basically' the same across browsers and operating systems - i.e. we'll have a ~90% success rate if we rely on them.
I cannot use a fly-by-night operation i.e. 'Fast Eddie's SSL Certificate Clearing House -- with prices this low our servers MUST be hacked!'
Nice to Haves:
I don't want the user warned that the certificate's hostname doesn't match the hostname in the browser. I consider this a nice-to-have because it may be impossible.
Do not want:
I don't want to ship the same set of static keys for each box. Kind of implied by the 'can't' list, but I know the risk.
Yes Yes, I know..
I can and do provide a mechanism for the user to upload their own cert/key but I consider this 'advanced mode' and out of scope of this question. If the user is advanced enough to have their own internal CA or purchase keys then they're awesome and I love them.
Thinking Cap Time
My experience with SSL has been generating cert/keys to be signed by 'real' root, as well as stepping up my game a little bit with making my own internal CA, distributing internally 'self-signed' certs. I know you can chain certificates, but I'm not sure what the order of operations is. i.e. Does the browser 'walk up' the chain see a valid root CA and see that as a valid certificate - or do you need to have verification at every level?
I ran across the description of intermediate certificate authority which got me thinking about potential solutions. I may have gone from 'the simple solution' to 'nightmare mode', but would it be possible to:
Crazy Idea #1
Get an intermediate certificate authority cert signed by a 'real' CA. ( ICA-1 )
ROOT_CA -> ICA-1
This certificate would be used at manufacturing time to generate a unique passwordless sub-intermediate certificate authority pair per box.
ICA-1 -> ICA-2
Use ICA-2 to generate a unique server cert/key. The caveat here is, can you generate a key/pair for an IP (and not a DNS name?)? i.e. A potential use-case for this would be the user connects to the box initially via http, and then redirects the client to the SSL service using the IP in the redirect URL (so that the browser won't complain about mismatches). This could be the card that brings the house down. Since the SSL connection has to be established before any redirects can happen, I can see that also being a problem. But, if that all worked magically
Could I then use the ICA-2 to generate new cert/key pairs any time the box changes IP so that when the web server comes back up it's always got a 'valid' key chain.
ICA-2 -> SP-1
Ok, You're So Smart
Most likely, my convoluted solution won't work - but it'd be great if it did. Have you had a similar problem? What'd you do? What were the trade offs?
Basically, no, you can't do this the way you hope to.
You aren't an intermediate SSL authority, and you can't afford to become one. Even if you were, there's no way in hell you'd be allowed to distribute to consumers everything necessary to create new valid certificates for any domain, trusted by default in all browsers. If this were possible, the entire system would come tumbling down (not that it doesn't already have problems).
You can't generally get the public authorities to sign certificates issued to IP addresses, though there's nothing technically preventing it.
Keep in mind that if you're really distributing the private keys in anything but tamper-proof secured crypto modules, your devices aren't really secured by SSL. Anyone who has one of the devices can pull the private key (especially if it's passwordless) and do valid, signed, MITM attacks on all your devices. You discourage casual eavesdropping, but that's about it.
Your best option is probably to get and sign certificates for a valid internet subdomain, and then get the device to answer for that subdomain. If it's a network device in the outgoing path, you can probably do some routing magic to make it answer for the domain, similarly to how many walled-garden systems work. You could have something like "system432397652.example.com" for each system, and then generate a key for each box that corresponds to that subdomain. Have direct IP access redirect to the domain, and either have the box intercept the request, or do some DNS trickery on the internet so that the domain resolves to the correct internal IP for each client. Use a single-purpose host domain for that, don't share with your other business websites.
Paying more for certificates doesn't really make them any more or less legit. By the time a company has become a root CA, it's far from a fly-by-night operation. You should check and see if StartSSL is right for your needs, since they don't charge on a per-certificate basis.

Resources