LDAP over TLS with ldap-client in node - javascript

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.

Related

how can I force fetch to accept a self-signed certificate in a web app front end?

I am prototyping a simple web app front end that needs to fetch JSON data from my server. The server itself works fine -- I can click on the link, and the JSON data shows up in the browser. But the following simple script fails:
fetch('https://x.x.x.x:8000') // MY URL FAILS
// fetch('https://jsonplaceholder.typicode.com/todos/1') // ALTERNATE URL WORKS
.then(function() {
alert("Successful")
})
.catch(function() {
alert("Failure")
});
I'm completely new to this sort of front-end work (and to Javascript in general), so I might be overlooking an obvious reason, but the two that come to mind are
my server uses a self-signed certificate for testing purpose; and/or
I'm using a non-standard port.
The first of these possible explanations seems more likely.
Accessing the web page generates a bunch of errors, none of which mean anything to me (except for not finding the favicon):
I will temporarily post the full URL in a comment below, in case anyone else wants to see what happens, but I would delete it once a working solution is suggested.
To answer your question as asked, no, you definitely can't use fetch to force the client (browser) to ignore cert errors. Especially in cross-origin requests (and going from one port to another is cross-origin), that would be a HUGE security hole. It would allow anybody who could get a man-in-the-middle position on a victim's network (not hard) to steal information from the victim's HTTPS connections using fraudulent certificates to intercept the HTTPS requests and responses.
You might be able to force server-side JS (in Node or similar) to ignore cert validation errors, since in that case you (hopefully!) control the code the server is running. But it doesn't look like that's what you're doing, and in a web page, somebody else (the server owner) controls what code you (the browser) are running, so you definitely can't let that code turn off important security features!
Attack scenario for if JS could turn off cert validation:
Suppose you and I both control web servers. I, a malicious attacker, would like to intercept the traffic between your users and your web server. I even have a man-in-the-middle (MitM) network position on some of your users! However, you are of course using TLS (via HTTPS), so I can't decrypt or modify the traffic.
However, your users sometimes connect to my server as well, not knowing it is malicious (maybe I mostly use it to serve relatively innocuous stuff, like a comment system or analytics tools, so lots of sites embed my scripts). My server can tell when a browser requests content from an IP address where I could launch an MitM attack, and serve them malicious scripts.
Now, in the real world, this doesn't matter! Sites don't trust other sites, because of the Same-Origin Policy, a critical browser security feature. My site (or the scripts I serve) can cause your users to submit requests to any other server that I choose, but they can't read the responses (if the other server is cross-origin), and they can't turn off certificate validation so my MitM position is mostly useless.
However, suppose that there was a way - as you propose - for scripts to tell the browser "it's ok, just trust this one particular self-signed cert when making this request". This changes everything. My MitM host will generate a self-signed cert (and corresponding private key) for your site, and send the cert to my own web server. When a potential victim loads a script from me, it only only contains instructions to make HTTP requests to your site, it also specifies that the browser should trust the self-signed certificate that my MitM node generated.
The victim's browser would then start the request, attempting to establish a TLS connection to your server. My MitM node would intercept the request, and reply with its self-signed certificate. Normally the browser would reject that, but in this case it doesn't because you created a way to tell browsers to accept a particular self-signed cert. Therefore, the victim's browser trusts my self-signed certificate. The actual request never even makes it to your server. The victim's browser, believing itself to be interacting with the legitimate server (yours) rather than with my MitM host, sends an HTTP request containing secrets such as cookies and/or API keys / bearer tokens / login credentials / etc. My MitM intercepts that (as it's intercepting all traffic), decrypts it (because it is in fact one end of the TLS tunnel, this is trivial), and can access the victim's account on your server. (My MitM host can also duplicate the responses from your server that the victim would usually see, to keep them unsuspecting. The MitM host can even tamper with this responses, if I want it to mislead the user.)
The usual way to solve this is to install the server's certificate as trusted in the browser (or in the OS). That way, the browser will recognize the certificate's issuer (itself) as valid, and consider the certificate valid.
What happens if you go to https://x.x.x.x:8000/ in the browser directly? If you get a certificate error, well, that's your problem: the browser doesn't trust the certificate of the server hosted on that port. You should have an opportunity to temporarily or permanently trust that certificate (exact details will depend on the browser).
Note that, of course, doing this on your own computer won't fix it for anybody else's computer. They'd need to manually trust your certificate too.
The actual solution is, of course, to install a trusted certificate. Perhaps you should try Let's Encrypt or similar, for a nice free cert that every client will trust without extra shenanigans?
Just had the same problem and stumbled upon the solution by accident. It is possible by just making the user open the self-signed site, click on 'Show more' and 'Accept the risk and continue'. After doing that, fetch requests go through like nothing ever went wrong.
It works on Firefox:
and Chrome:
This method just has the caveat that you have to do the setup, and on Chrome it displays 'Not secure' even when the rest of the page is secure.
But if you need HTTPS locally, this works like a charm. Hope this helps the people who came here from Google :)
EDIT:
Also worth mentioning, I tested it on localhost but it works everywhere.

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)

Detect on the server-side if a client rejects my TLS certificate

I'm building an HTTP proxy in Node.js, which attempts to intercept HTTPS connections, using a self-signed certificate. I'm using a bare http.Server, instantiating my own tls.TLSSocket to upgrade sockets as required, and the functionality all works great when the CA is trusted by the client.
If the client isn't configured with the CA though, it obviously rejects the connection, complaining that there's a self-signed certificate in the chain.
That's all as it should be, but I'd like a way to detect that this has happened from the server-side, so I can prompt the user to correctly configure their client.
Is it possible to do this? It seems the TLS RFC (https://www.rfc-editor.org/rfc/rfc5246#section-7.2.2) has quite a few error alert messages about certificate rejections, which I would expect to cover this, but I can't see to see any debug info in Node about those even with NODE_DEBUG=tls.
Really I'd like to subscribe to TLS error alert events, so I can react to the various interesting cases in there directly. How can I do that?
Usually all what you see is that the client closes the connection. Some clients might send an alert, others don't - the exact behavior depends on the TLS stack. Anyway, you could not redirect the client from within this dead connection anyway.
What you might try is to have some initial page served with plain HTTP where you include some image or similar from a HTTPS resource using a certificate signed with your CA. With some script you can detect if the client has successfully loaded the image or not and in the latter case you can show your information about needing to install some certificate.

Using SSL from a CA for server + allowing ssl client authorization that is self-signed with Node.js

First time working with SSL client authentication. The way it works with node.js while mixing with a certificate issued by a third-party CA (in this case it is StartSSL) is confusing me.
On production servers I'm using nginx as load balancer to different node.js instances. Since this is how I had done it before, nginx is handling all the HTTPS work and then passing a plain http request to a node instance. Since it has been deciding to always enforce SSL (for all kind of requests, using HSTS and using simple redirects), I'm considering the possibility to moving into having nginx doing only the balancing and letting the nodejs instances take care of the rest.
So, what I ignore is how to handle this with Node.js?
I found this blog post http://www.gettingcirrius.com/2012/06/securing-nodejs-and-express-with-ssl.html and this other http://blog.nategood.com/nodejs-ssl-client-cert-auth-api-rest
What I don't understand is how to handle both SSL authentications simultaneously. I hope I'm making some sense.
The idea is to generate a certificate for each user which has a CN that I match to a user, then ask for a password that, after bcrypted, should match what is on the database. While, at the same time, using the verification level 3 certificate that works with the CA to improve our users' safety.

Encryption: simulate SSL in javascript and python

Because of china Great Firewall has blocked google appengine's https port. So I want to simulate a Secure Socket Layer by javascript and python to protect my users information will not be capture by those ISP and GFW.
My plan:
Shake hands:
Browser request server, server generate a encrypt key k1, and decrypt key k2, send k1 to browser.
Browser generate a encrypt key k3, and decrypt key k4, send k3 to server.
Browse:
During the session, browser encrypt data with k1 and send to server, server decrypt with k2. server encrypt data with k3 and response to browser, browser decrypt with k4.
Please figure out my mistake.
If it's right, my question is
how to generate a key pair in
javascript and python, are there
some libraries?
how to encrypt and decrypt data in
javascript and python , are there
some libraries?
You have a fundamental problem in that a JavaScript implementation of SSL would have no built-in root certificates to establish trust, which makes it impossible to prevent a man-in-the-middle attack. Any certificates you deliver from your site, including a root certificate, could be intercepted and replaced by a spy.
Note that this is a fundamental limitation, not a peculiarity of the way SSL works. All cryptographic security relies on establishing a shared secret. The root certificates deployed with mainstream browsers provide the entry points to a trust network established by certifying authorities (CAs) that enable you to establish the shared secret with a known third party. These certificates are not, AFAIK, directly accessible to JavaScript code. They are only used to establish secure (e.g., https) connections.
You can't stop the men in the middle from trapping your packets/messages, especially if they don't really care if you find out. What you can do is encrypt your messages so that trapping them does not enable them to read what you're sending and receiving. In theory that's fine, but in practice you can't do modern crypto by hand even with the keys: you need to transfer some software too, and that's where it gets much more awkward.
You want to have the client's side of the crypto software locally, or at least enough to be able to check whether a digital signature of the crypto software is correct. Digital signatures are very difficult to forge. Deliver signed code, check its signature, and if the signature validates against a public key that you trust (alas, you'll have to transfer that out of band) then you know that the code (plus any CA certificates – trust roots – sent along with it) can be trusted to work as desired. The packets can then go over plain HTTP; they'll either get to where they're meant to or be intercepted, but either way nobody but the intended recipient will be able to read them. The only advantage of SSL is that it builds virtually all of this stuff for you and makes it easy.
I have no idea how practical it is to do this all in Javascript. Obviously it can do it – it's a Turing-complete language, it has access to all the requisite syscalls – but it could be stupidly expensive. It might be easier to think in terms of using GPG…
(Hiding the fact from the government that you are communicating at all is a different problem entirely.)
The other answers here are correct: You won't be able to securely deliver the JavaScript that is going to be running on the client. However, if you just want to look into this stuff some more anyway, check out the opensource project Forge. It has an SSL/TLS implementation in JavaScript and a simple Python SSL server:
http://github.com/digitalbazaar/forge/blob/master/README
If you want to read up some more on its uses:
http://digitalbazaar.com/2010/07/20/javascript-tls-1/
http://digitalbazaar.com/2010/07/20/javascript-tls-2/
There's a big problem, if security really is a big concern: Your algorithm is going to be transfered unsecured. Can you trust the client at all? Can the client trust the server at all?

Categories

Resources