Hows is ssl certificate verified and by a browser or server - javascript

I've created a self-signed sertificate
$ openssl genrsa -out key.pem 1024
$ openssl req -new -key key.pem -out request.csr
$ openssl x509 -req -in request.csr -signkey key.pem -out cert.pem
and created an HTTPS server:
var server = https.createServer({
key: fs.readFileSync(__dirname + "/key.pem"),
cert: fs.readFileSync(__dirname + "/cert.pem")
}
Then I requested the page. The expected result is that a browser complained that a connection is not secure. My question how does a browser know that? Is it server job to verify the certificate and notify browser about that or it's a browser job?

SSL Certificates are verified by the client.
The server typically will verify the certificate is not broken or corrupt on start-up, but most servers don't actually validate the legitimacy of their certificate.
Why verify the certificate?
Verification of the server certificate is important because otherwise the client can't really know who it is communicating with. MITM (Man In the Middle) attacks can take place where a third party is intercepting both sides of the communication and they can provide their data to you instead of the data from the server which you thought you were receiving.
A little bit about certificate types
Most certificates are signed by CAs, there are also self-signed certificates, and pinned certificates. I advise using a certificate signed by a CA whenever possible. The Second best option (which generally can only be used within an organization) would using your own internal CA and then self-signing your server cert with your CA cert, this is known as a self-signed certificate and it won't be trusted automatically by any clients or browsers which receive it.
In the self-signed option you must import your CA public key into your CA key store for your server certificate to be trusted. Finally there is simply a pinned certificate, this is where you simply tell your browser to trust an otherwise untrusted certificate (do not do this).
Warning - You should avoid pinning certificates because they are almost impossible to replace during a compromise, and certificates should be schedule to expire within a reasonable period, and be regularly rotated. Pinning makes that very difficult if almost impossible in some situations.
Types of certificates
CA Signed (Needed to operate a secure site on the WWW)
Self Signed (Good for internal organization usage, internal company wikis for example)
Pinned (Avoid)
What kind of verification happens?
So you have a certificate, first you configure your server to use that certificate.
Now when a client comes along and requests a secure connection to your site (as indicated by connecting to port 443 in in the case of HTTPS). Your server sends it's public (not private) certificate and begins a secure handshake. One such handshake is called a Diffie–Hellman key exchange. The handshake itself is beyond the scope of this question.
Before participating in the key exchange, the browser will first examine the certificate which the server provided. For it to be valid several checks must be successful.
There are some of the checks performed.
Does this certificate contain the hostname which matches the hostname we connected to?
If NO, does the certificate include a wildcard CN (Common Name)?
If YES, does that CN have a valid "wildcard" that matches the host name we're connected to? YES/NO
Does the certificate include a CRL (Certificate Revocation List)? If so, does that CRL indicate that this certificate is still valid? YES/NO
Is this certificate signed by a known certificate authority (CA)? YES/NO
Only if NO, does this client (browser) have a public certificate (which matches the certificate offered by this server), which has been marked as Trusted? YES/NO *This is also known as a pinned certificate, as you are not relying on a CA to verify it's authenticity.
For the browser to trust the certificate, and by proxy the server. Then we must check each of the Yes boxes above
Other security stuff that makes the world safer
Now there are other things not "specific" to the certificate which are also verified.
For example, both the client and server must agree on the handshake method, the ciphers used, the hashing algorithm used, and other things.
The server may also pass special HTTPS security flags instructing the browser not to trust other certificates for this service for a period of time (this is known as certificate pinning). Certificate pinning like that used in "Strict Transport Security" (not to be confused with pinning a certificate as mentioned above) can help prevent MITM (man in the middle) attacks. This is one of the many extra security features that HTTPS Strict Transport Security offers.
Once all of the security checks have been certified the browser sends any request it had to the server and the server responds appropriately.

When you visit a secured website (with https), the server also sends a certificate signed by an authority to prove its identity (so that you know you're not getting man in the middled).
Then, your browser needs to know if the certificate is genuine or not, because the man in the middle could send a certificate too. Luckily for you, your browser has a list of authorities to trust. If the certificate's authority signature matches one of the trusted authorities, then everything is fine and no alert is raised.
But if no authorities matches, then the browser kindly asks you if we can trust this authority. In the case of a self-signed certificate, you can trust it (but not before verifying the fingerprint, because, again, a man in the middle could send a different certificate to trick you into believing they're the real deal).
If you trust it, then the browser imports it and adds it to the certificates to trust, never raising an alarm again (until your certificates expires or change (like in a man in the middle situation)).

Is it server job to verify the certificate and notify browser about that or it's a browser job?
The main role of the server certificate is to make sure that the client is communicating with the expected server.
If the client (browser) would just trust the server that the certificate is valid some man in the middle attacker could simply claim to be the real server and claim that the certificate is valid. And after this the client would establish the encrypted connection to the attacker instead of the real server which means that the attacker gets access to the sensitive data. Therefore the servers certificate must always be properly checked by the client.
My question how does a browser know that?
In short: by checking that the certificate is trusted by checking the signature of the issuer and following the trust chain up to a locally trusted root certificate, also checking that the hostname of the URL matches the subject of the certificate and that the certificates are still valid, i.e. not expired and not revoked. For more details see SSL Certificate framework 101: How does the browser actually verify the validity of a given server certificate?.

Related

Download client over ssl but connect to arbitrary IP

In browsers, is it possible to request javascript for a web-client over https, but have said client connect with a websocket to an IP either:
without ssl
with a self-signed certificate (without previously adding the certificate to the browser)
From what i read, it simply isn't. Mixed content is forbidden, and self-signed certs are not accepted, unless the user goes through a weird and dangerous looking menu, to manually accept the certificate in the browser. It's not like the typical user has the qualification to check a certificate anyways.
This would directly imply, that for this case, encryption cannot be used at all, sadly.
Isn't there something i overlooked? If the websocket connection wasn't over ssl, the client could even just encrypt itself, inside a non-ssl connection. The server it's connecting to won't have a certificate from a CA, it typically won't even have a domain.
Edit: some background
The desired situation is as follows:
a user enters a website, and gets served a client via a secure connection (this is from a static domain, so having a certificate from a CA is no problem here. However, using https apparently disallows non-ssl-connections from that site, and the client accordingly).
the client then opens a websocket connection to a server IP, which may arbitrarily vary (can even be multiple servers at the same time), and typically has no domain. For this, i can only come up with a few scenarios:
no ssl (forbidden, mixed content)
self-signed certificate, preferably the client would get the public key from the main domain, and have that pinned (self-signed produces warnings, and users can't really be required to manually install certificates just for this)
Some CA offers free and automated certificates for IPs, which we can depend on, and just generate new certificates whenever necessary, without any human action needed (i didn't consider this before, because i simply didn't think any CA would offer such a thing. Maybe there is, but so far, i've not encountered any)

How to install ssl for mosquitto

I have followed the instructions here: http://www.steves-internet-guide.com/mosquitto-tls/ to enable ssl.
It is a self signed certificate and when I try to access the broker over the internet from a web page, I get ERR_CERT_AUTHORITY_INVALID.
When I type the websocket address as https://websocketaddress/, I get the warning and when I click proceed and then reload the page accessing the websocket address, I am able to access the broker and get values.
So it is because it's a self signed certificate, I get that error.
My question is what is the procedure to add ssl after I buy the certificate from a CA?
Yes, it is because you are using a self signed certificate.
If you are using a self signed certificate then you have to manually distribute the CA cert to EVERY client that wants to use the broker.
As I said in the answer to your last question about this, if you want it to be accessible to everybody on the internet then you will need to use a certificate from a trusted public CA. The CA cert from these sources are already included in the browser so you don't need to add them.
You can either pay a CA for a certificate that will most likely come with a years life, or you can use LetsEncrypt who will supply a free certificate with a 90 day life, but they also supply a tool that can renew the certificate for you and you can script it to update the certificate then restart mosquitto.
The procedure for setting up mosquitto will be the same, you just need use the files from the CA.
For a paid for Certificate, you will generate a private key, then from that create a CSR (Certificate Signing Request) which you send to the CA and they will send back a certificate.
For LetsEncrypt, the command line tool will handle creating a private key and CSR for you and sending it to the CA to get a certificate. The files will be stored in /etc/letsencrypt/live/[hostname]/. Make sure you use the fullchain.pem for the CA cert entry in mosquitto.conf.

LDAP over TLS with ldap-client in node

I am fairly new to the concept of domains and am trying to implement LDAP over TLS in node. And I have been stuck with this issue for many days now. I am using ldap-client.
var LDAP = require('ldap-client');
var ldap = new LDAP({
validatecert: false, // Verify server certificate
...
}, function(err) {
// connected and ready
});
so with some research I came into conclusion that, if the field validatecert is to be set amount these values
LDAP.LDAP_OPT_X_TLS_NEVER = 0;
LDAP.LDAP_OPT_X_TLS_HARD = 1;
LDAP.LDAP_OPT_X_TLS_DEMAND = 2;
LDAP.LDAP_OPT_X_TLS_ALLOW = 3;
LDAP.LDAP_OPT_X_TLS_TRY = 4;
which was quoted under the section TLS in the library documentation
TLS can be used via the ldaps:// protocol string in the URI attribute on instantiation. If you want to eschew server certificate checking (if you have a self-signed cserver certificate, for example), you can set the verifycert attribute to LDAP.LDAP_OPT_X_TLS_NEVER, or one of the following values:
With which I could setup a secure connection.
I know that we need certificates for TLS connection to work. One is held by the server and another by the client (me).
My question is if I set the field to any of the said methods:
How am I to verify that my connection is secure ?
Where do I see the certificates or not see them at all ?
Do I have to manually generate certificates from the server and use them ?
Certificates are a means to help others verify that the entity presenting the certificate is indeed who it is claiming to be. Thus, when you connect to a server and server returns a certificate, then through that certificate you can be sure that server is indeed the server and not an imposter.
The power of certificate is due to the issuer (also called Certificate Authority or CA). If you trust the issuer, then you effectively trust the certificates issued by it. A list of prominent CAs is usually present in the OS itself, so getting a certificate and verification of that certificate is transparent to the application developer, especially when you are using libraries.
Taking your points one by one:
I know that we need certificates for TLS connection to work. One is held by the server and another by the client (me).
You didn't ask any question here, here is some general info. Usually server verification is all that's needed. In high security environments, client verification is done too and there you (i.e. the client) would need a certificate from a CA to verify yourself to the server. But, in most applications, server verification is sufficient.
It is similar to Normal Forms in RDBMS normalization. Even though you have Normal Forms as strict as 6NF, usually RDBMS's are normalized till 3NF.
How am I to verify that my connection is secure?
Generally, if you are using a well known library, (like curl or openLDAP) calling its secure connection methods is enough. It is very very unlikely that you called a function that the library claims to be secure but it turns out to be a farce.
To be sure though, you can look at your traffic with the server. Wireshark is often used for network traffic analysis.
Where do I see the certificates or not see them at all?
In most cases you don't see the certificates. All you do is tell your library how strict you want the verification to be. And then your library will take care of the rest - often throwing an exception or logging an error if there is some issue with the certificate.
If you are using a client certificate then you would have to keep it on the file system and point your library to it. It is generally a .pem file.
Do I have to manually generate certificates from the server and use them?
No. For server certs, it is the responsibility of the server to provide you with a valid cert. All you have to do is just check that the certificate sent by server is from an established CA - which, as told earlier, is generally a transparent step for the developer using the library.
In cases where you do not care much or in situations where you want to start coding and CA is yet to issue a certificate for you, you can program the server to provide its clients with a self-signed certificate and program the clients to keep the verification less strict.
A self-signed certificate has little value in terms of security. It is like server saying - 'Hey, I'm telling you that I'm the guy you want to talk to.' That clearly isn't enough. You want a third person (i.e. the CA), whom you fully trust, to confirm that that is the guy you wanted to talk to.

Clarification for sending credentials via HTTPS

I have a website that is running on a server that integrates with the JIRA REST API. In order to authenticate requests, the site asks for the user credentials and sends those to JIRA to return back a session (see this).
Obviously, I don't want these credentials floating around in plaintext. While this will be run on an internal network that does not face the outside, it is still important.
My question is (excuse the poor explanation): Do I need to acquire an SSL cert for MY server even if JIRA is using HTTPS. In this instance, JIRA has a valid SSL cert and is secured by HTTPS.
Rough overview of the 'flow':
User enters user/pass and submits HTML form (index.html on nodejs) ->
-> Request (HTTP POST) is sent to my server w/ creds (nodejs)
-> My server sends a request to JIRA (HTTPS)
<- JIRA responds with JSON
<- Response is received by my server
<- My server sends data back to index.html
My thinking is I need HTTPS in this case due to this:
XX.XX.XX.XX <-/-> YY.YY.YY.YY <---> ZZ.ZZ.ZZ.ZZ
[XX] = client (index.html)
[YY] = server (nodejs)
[ZZ] = JIRA
In that 'diagram', the client sends the credentials to my server over HTTP, which is insecure. The server will then send the credentials to JIRA, which does have HTTPS enabled.
In this case, I'm assuming the credentials can be sniffed between X and Y, but not between Y and Z (I'm starting to confuse myself...)???
(P.S. I needed to put a server in the middle due to CORS limitations. Everything is working fine other than the HTTPS issue.)
You're right : the HTTP communication between the client X and your server Y is in clear text if there is no SSL configured on server Y. The credentials can be sniffed there, but can't be between Y and Z.
You can easily check with a tool like wireshark : https://www.wireshark.org/, if you run it on X or Y (or anything in between that might see the packets). Or the tcpdump command-line of you don't have a GUI (on Unix/Linux).
To secure this, you indeed need to switch to HTTPS on server Y, which implies to put a SSL certificate on it. You can test with a self-signed certificate (but the browsers will complain about it), and then put a valid certificate : as you seem to be in a corporate environment, you might have a corporate certificate authority trusted by your internal browsers.
Assume the credentials can be sniffed everywhere, encrypt everything.
Request (HTTP POST) is sent to my server w/ creds (nodejs) is HTTP, not HTTPS, that is a security issue. Get a certificate and setup HTTPS with TLS 1.2.
Remember is is the user who suffers if the security is bad, put yourself in their place, do you expect the services you use on the Internet to have best practice security?

Is it possible to generate a SSL certificate in the browser?

For an administration interface we want to implement client authentication with SSL. The idea is that during the registration process every user generates a SSL certificate, which is registered in the browser and used for authenticating the client to the server. It is important that the private key never leaves the client. Hence it is no solution to generate the certificate on the server and send it to the client.
Is it possible to generate a SSL cert in the browser (e.g. IE 9+, Firefox 12+, Chrome) using JavaScript? Is it possible to register a certificate?
You can't really generate a certificate in the browser, but you can generate a certificate request (or equivalent) in the browser: the key-pair is generated within the browser and the private key never leaves it.
(Note that if you generated a certificate directly within the browser, it would at best be self-signed, since the CA wouldn't give you its private key. That's why you only get to have a certificate-request, since there's little demand for generating self-signed certificates. I think there's a Firefox extension that could do it, though.)
The certificate request is sent to the server, but the format depends on the browser and the method used. What you'll get on the server side is the public key, it's up to the service you implement to turn it into a certificate (unless you use an existing service of course). You can find more details about this in this answer.
Once the certificate is generated on the server, it can be re-imported back to be associated with the private key.

Categories

Resources