How do you get Mozilla FireFox to accept your root Certificate Authority ssl cert so it doesn't complain about self-signed ssl certs on https? - ssl

First I want to point out that this works fine with Internet Exporer 11. But for some reason I just can't get FireFox to play nice!
So I already added my own rootCA security certificate and under Internet explorer it works fine and my website with self-signed cert is trusted.
But on Firefox v61.0.1 and also v65.0 even though my root certificate is already added, and in addition security.enterprise_roots.enabled is set to true (in about:config), I still get the "your connection is not secure" message and I have to add a security exception just to view my site.
In the area with the message and button to add exception, Firefox says:
"xx.xxx.xx.x uses an invalid security certificate. The certificate is only valid for xx.xxx.xx.x. Error code: SSL_ERROR_BAD_CERT_DOMAIN"
Now the xx.xxx.xx.x is an internet reachable IP address and both instances in the above line have exactly the SAME IP address, I've used IP for the CN field.
clicking on SSL_ERROR_BAD_CERT_DOMAIN shows:
"Unable to communicate securely with peer: requested domain name does not match the server’s certificate. HTTP Strict Transport Security: false HTTP Public Key Pinning: false Certificate chain: -----BEGIN CERTIFICATE----- ......."
Anyway, I am guessing that in its current configuration, Mozilla FireFox is CONFUSED that the site has an invalid certificate when in fact it is valid and the reason for its confusion is perhaps it expects a domain-NAME not IP address.
If so, is there a way I can tell Firefox to honor IP Address based ssl certs?
Again, current config is working perfectly fine with Internet Explorer for me.
As you know many tools like built-in IDE svn and other source control clients really do not like it when there's something to complain about in an ssl-cert.
That's the reason I went through trouble of creating and loading own Root CA Authority in windows. And no please do not recommend letsencrypt, needs renew often and I don't have incoming OPEN ports which it seems to require to renew.
thx!

Hooray! Success :) I went by my what I thought was confusion over IP vs name and discovered that my extfile under the [alt_names] section I had used DNS.1 = xx.xxx.xx.x
So I simply edited my extfile and changed DNS.1 = ... to now be IP.1 = xx.xxx.xx.x
Then I simply recreated my webserver's cert. For anyone wondering, here's actual command:
openssl x509 -req -in mywebserver.csr -CA myrootCA.pem -CAkey myrootCA.key -CAcreateserial -out ./certs/mynginxwebserverIP.crt -days 2555 -sha256 -extfile myextfile.cnf
That overwrote my current .crt file and all I needed to do was nginx -s reload and bingo!
Well hope that helps someone cuz it was driving me crazy!
Now it works just fine in Firefox and I get that comforting nice green lock :)
And internet explorer didn't know/care about the difference, worked both ways :D

Related

Can't make Guzzle accept a certificate

I'm trying to have a server A communicate with a server B through HTTPS requests. Server B has a certificate that was issued to me by my employer, and connecting to it through both Safari and Chrome works without any issues.
However, when trying to send a request from A to B through Guzzle, I get the following error:
GuzzleHttp/Exception/RequestException with message 'cURL error 60: SSL certificate problem:
unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)'
I've tried setting the cert file as a parameter ( [verify => '/path/to/cert.pem'] ), but, first of all, I only had .crt, .csr and .key files; I tried making a .pem file through these instructions I found somewhere else:
(optional) Remove the password from the Private Key by following the steps listed below:
openssl rsa -in server.key -out nopassword.key
Note: Enter the pass phrase of the Private Key.
Combine the private key, public certificate and any 3rd party intermediate certificate files:
cat nopassword.key > server.pem
cat server.crt >> server.pem
Note: Repeat this step as needed for third-party certificate chain files, bundles, etc:
cat intermediate.crt >> server.pem
This didn't work – the error's the same. The request works with 'verify' set to false, but that's obviously not an option for production.
Certificates are not something I usually work with, so I'm having a lot of trouble just figuring out where the issue might lie, let alone fix it. Any help would be much appreciated.
Edit
I've also tried the solutions suggested in Guzzle Curl Error 60 SSL unable to get local issuer to no avail.
This was happening because the only certificate I had configured on server B was the End User certificate.
I'm new to this, so my explanation will probably be flawed, but from my understanding End User certificates link back to a trusted Certificate Authority (CA) certificate, with zero or more intermediate certificates in-between. Browsers can figure out this certificate chain, and download the required certificates that are missing; cURL does not.
Therefore, the solution was configuring Server B with the missing certificates. How to do this is a whole different issue, so I won't go into it in this answer.

Chrome does not send client certificate, while certificate is valid

I am witnessing a weird issue with regards to mutual authentication.
I have setup mutual authentication on BigIP loadbalancer to accept 2 different CAs.
This means that we only accept certificates that has been issued by those 2 CAs.
I have tried providing those certificates to LB using OpenSSL and it works fine by this i mean i have 2 certificate, Using IE it works fine as well, FireFox it works fine as well. but when i use chrome, browser asks for certificate but it doesnt send the certificate to the LB, as it has been observed in wiresharks (Picture to follow)
I have access to both certificates, so i extacted the certs and key and used
openssl s_client -connect Host:port -cert "cert.pem" -key "key.pem"
It works fine, and i can see connection is ok.
Using same certificates in IE, it works as well.
Postman works as well.
FireFox Works as well.
Chrome however it shows certificate length as 0
And as you can see same certificate is used by OpenSSL and it is sending.
Any idea what might be the problem?
Update :
I started chrome with debug and saw this, it seems chrome cannot parse my key or cert.
[14836:18604:0927/172254.921:ERROR:ssl_platform_key_util.cc(70)] Could not parse public key.
[17536:16164:0927/172255.100:ERROR:ssl_client_socket_impl.cc(941)] handshake failed; returned -1, SSL error code 1, net_error -117
In my case, there was a problem with the ASN.1 encoding of the Algorithm Parameters in the certificate. The encoding missed a NULL value. If you upload your certificate, we can double-check.

Securing a private IP address (https certificate)

I have an unusual use case :
a web server on the Internet is serving pages through HTTPS,
inside those web pages, there are calls to XMLHttpRequests to a locally connected device (IP over USB)
the device supports both HTTP and HTTPS,
the device is accessible on http(s)://192.168.0.1
the http calls fail because of insecure content in a https page,
the https calls fail because the certificate is not trusted (self-signed),
Side question: Since the device is locally connected to the PC, the encryption is pretty useless: Does a http header exists that allows insecure connections to a specific URL ? (like CORS for cross domain)
Main question: Is it possible to obtain a certificate for a private IP address ?
Edit: it seems that Plex had a similar problem and solved it the way described on this blog. This is a way too big for me.
Is it possible to obtain a certificate for a private IP address ?
A certificate can be bound to an IP address (see this). You can issue a self-signed certificate to a private address, but a trusted CA will not issue a certificate to a private address because it can not verify its identity.
For example a certificate issued to 192.168.0.1 would be theoretically valid in any context, and this should not be allowed by a trusted CA
Plex solves the problem with a Dynamic DNS and a wildcard certificate. The connection are done using the name (not the IP) of the device which is resolved to the private IP
Does a http header exists that allows insecure connections to a specific URL ? (like CORS for cross domain)
No, it does not exist. The browser blocks your XHR connections because they are HTTP connections initiated from a HTTPS page (mixed-content warning). Non-secure content can theoretically be read or modified by attackers, even though the parent page is served over HTTPs, so is normal and recommended that the browser warns the user.
To fix the mixed-content and https errors, you could serve the content through HTTPS and a self-signed certificate, and request users to import your root CA at browser.
An SSL certificate cannot be issued for Reserved IP addresses (RFC 1918 and RFC 4193 range)/ private IP addresses (IPv4, IPv6), Intranet for Internal Server Name, local server name with a non-public domain name suffix.
You could however use a 'self-signed' certificate. Here's how to create one:
Creating a Self-signed Certificate for a private IP
(example https://192.168.0.1) :
You need OpenSSL installed.
For example, on Ubuntu, you could install it by: sudo apt-get install openssl
(It may already be installed. Type "openssl version" to find out)
For Windows, you could try this: https://slproweb.com/products/Win32OpenSSL.html
Once OpenSSL is installed, go to OpenSSL prompt by entering 'openssl' on the console (LINUX), or the cmd prompt (WINDOWS).
$ openssl
OpenSSL>
Now do the following steps to create: Private key, Certificate Request, Self-signing the certificate, and putting it all together, by using the below commands:
i) Create KEY called mydomain.key:
OpenSSL> genrsa -out mydomain.key 2048
ii) Use the key to create a Certificate request called mydomain.csr
You could accept the default options, or specify your own information:
OpenSSL> req -new -key mydomain.key -out mydomain.csr
iii) use the above to create a certificate:
OpenSSL> x509 -req -days 1825 -in mydomain.csr -signkey mydomain.key -out mydomain.crt
iv) Put all the above to create a PEM certificate:
exit OpenSSL (OpenSSL> q) and go to certificate location and do:
$ sudo cat mydomain.key mydomain.crt >> mylabs.com.pem
mylabs.com.pem is your self-signed certificate. You can use this in requests like https://192.168.0.1 if your server supports https. Remember to check the port number for https(443).

Browser doesn't apply client certificate: 403.7

I'm trying to set up client certificate authentication. I was able to generate a CA-, server- and client-certificate. As long as I use Fiddler everything works as expected. However, as soon as I start using a browser it doesn't work anymore (HTTP Error 403.7 - Forbidden).
Of course I imported the client certificate in the Personal store and I made sure Client Certificate Negotiation is enabled.
I also tried openssl s_client -connect 127.0.0.1:443 -state -debug but I couldn't really make sense of the result... The only thing what's weird is that my CA doesn't show up in the Acceptable client certificate CA names section.
Anything else I could try?
Update:
I think it doesn't matter but my server certificate is set up for 127.0.0.1. Therefore I'm using https://127.0.0.1/... in my browsers.
Update2:
Using Wireshark I noticed that my servers' response depends on the client:
Fiddler (OK):
Client Hello
Server Hello, Certificate, Server Hello Done
Browser (Not OK):
Client Hello
Server Hello, Change Cipher Spec, Encrypted Handshake Message
Update3:
After enabling clientcertnegotiation the server response is different but still doesn't work:
Server Hello, Certificate
Certificate Request
Certificate, Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
My self-signed CA doesn't seem to be in the Distinguished Names list...
Update4:
SSL Settings: Checked Require SSL and Client certificates set as Required. Client cert shows up in Personal and the intended purpose is Client Authentication.
I finally found the issue and a workaround:
As mentioned in Update3, Distinguished Names doesn't contain my CA. This is because Distinguished Names has a limit of 2^14 bytes (16384 bytes). Because I do have a lot of CA installed on my machine my CA simply didn't make it in. The TLS standard would allow to send multiple messages but unfortunately Windows doesn't support this!
As mentioned here you have a few possibilities. The simplest one is this:
At your server add a DWORD (not QWORD!) value called SendTrustedIssuerList in your registry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL and set it to 0. This will prevent your server from sending a list at all, letting the client choose from any installed client certificate.
Unfortunately I couldn't see any traces in the Event Viewer (as reported elsewhere). Therefore the issue wasn't easy to spot (I had to use Wireshark in order to check Distinguished Names).
Use the Accept option instead of the Require option of the "Client certificates" feature.
In IIS Manager, locate the Web application for which you want to change the SSL setting.
In Features View, double-click SSL Settings.
On the SSL Settings page, select the Accept option under Client certificates.
In the Actions pane, click Apply.
More info here
Client certificate should be imported in CurrentUser\My store with private key (i.e. p12 or pfx file usually).
CA certificate should be in LocalMachine\Root store so that IIS trusts all certificates issued by the CA and the CA is trusted for every user on the computer.
CRL issued by the CA should be either available through URL (specified in every end entity certificate that CA issued) or imported in LocalMachine\My store.
NOTE: openssl doesn't use windows certificate store so this will have no efect on openssl s_client -connect 127.0.0.1:443 -state

IE8 SSL Cert Problems while other browsers work like a charm

I bought a SSL Cert which should work with iE 5+, but it doesn`t. All other browsers i tested work perfectly - no errors - just the site I want to display. But IE8 and smaller versions show an Error on the https...(they need to accept the ssl cert) site and destroy the layout on http version of the site (no https links included).
Non SSL
minol-fb.de/facebook-suche/
SSL
minol-fb.de/facebook-suche/
Ok it seems that browser < IE8 still use the self signed certificate..
You must have configured multiple certificates using Server Name Indication without knowing it.
If you use this, you get a self-signed certificate:
openssl s_client -showcerts -connect www.minol-fb.de:443
If you use this (with the server name), you get the correct certificate:
openssl s_client -showcerts -connect www.minol-fb.de:443 -servername www.minol-fb.de
You probably get a different behaviour with older versions of IE because you're testing them on XP. No version of IE supports SNI on Windows XP unfortunately. Other browsers (with sufficiently recent versions) do, at least independently on the OS version they run on.
If you don't need that other host, you can probably remove that configuration, so as not to have to rely on SNI at all.
Something odd is going on; if you use the link below you will see that the server is not returning the server cert and intermediate cert, but a single self signed Parallels Plesk Panel CA cert.
http://certlogik.com/ssl-checker/www.minol-fb.de
Using the openssl command below, I get the same Plesk certificate returned:
openssl s_client -showcerts -connect www.minol-fb.de:443
Perhaps this may help:
http://knowledgelayer.softlayer.com/questions/457/Installing+a+SSL+Certificate+in+Plesk+9
UPDATE:
Looks like you've sorted out the config; using the above tool I can see the correct certs are now being returned.
I ran into a similar situation where the cert was working OK on all browsers except for IE (of course!). This is on Apache and the SSL cert had been issued by RapidSSL. Turned out in my case, that I had virtual host file default-ssl active, so somehow IE was picking up on that on the default self-signed cert instead of the rapidSSL cert referred to in my site virtual host.
Deactivated ssl-default, reloaded apache and that did it.