27

I have to make a website for a NGO (Non-Governmental Organization), and they have the minimal options from their provider, so they can't have SSL/TLS (barely only HTML/PHP/MySQL/JS)

The data that goes from and to the server aren't very sensitive, but I don't want their passwords, name and address to be sent clear on the web.

I thought about ciphering data inside the JavaScript that calls the API functions with RSA (I'm no expert, but this lib seems pretty efficient), but I red an article that strongly advise not to use JavaScript for crypto (I'm French and maybe I didn't get everything right, but I got the main point).

So what should I use to cipher the data over the network?
If JS isn't really a bad idea, what can I do to ensure maximum safety with the technology I can use on this server (once again, no HTTPS, sadly), apart from importing the lib on my server and not relying on importing it from a different sever?

  • 40
    The article is correct; there is simply no good way to implement encryption between a webserver and client without using SSL/TLS. Without public-key infrastructure to verify the server's identity, MITM attacks would be trivially easy. Plus, anyone can simply strip/modify the javascript in transit. – tlng05 Dec 16 '15 at 15:01
  • 62
    It sounds like they need a new provider... – Ben Dec 16 '15 at 15:29
  • 4
    What's the point in encrypting the data when the Javascript code which does the encryption is sent in clear and unsigned? Hackers will set up a fake server which will have your interface, but none of your protective Javascript code, and simply log the passwords. – Dmitry Grigoryev Dec 16 '15 at 15:49
  • 9
    Step 1: confirm the provider really doesn't allow any TLS/SSL on their "basic" plan. It would be appalling if they didn't allow this when they give you a data store (and also worthy of public shame). You'll probably have to purchase a certificate, but disallowing the possibility of getting it set up is truly absurd. – jpmc26 Dec 16 '15 at 22:39
  • 6
    A lot of hosting providers, even if they don't offer individual SSL facilities, do have shared certificates which can be used by any user account. So instead of mydomain.com/login.html you would use something like hostingdomain.com/~mydomain/login.html (those pseudo links have https in front of them, it just doesn't display on the page) It isn't as neat as having your own certificate but it does offer a proper SSL/TLS option without any extra cost. It would be worth checking if this option is available,. – Mark_1 Dec 17 '15 at 9:33
105

No SSL, no security. Things in the real world are rarely simple, but here it is the case. This is easily seen as follows: whatever you do in Javascript, will be done in Javascript sent by the server. Any attacker who is in position to look at the data can also modify it at will (e.g. the easiest way to spy on WiFi is to run your own fake access point, and then you naturally get to modify all data as it comes and goes); thus, such an attacker can simply remove or alter whatever Javascript-based solution you may come up with, and deactivate it. Or just add a hook to also send the password in the clear as an extra parameter.

Now, even if you could get "safe Javascript" on the client browser, then you would run into all the problems that Javascript crypto entails, and that are detailed in the article you link to. But this is only a secondary consideration, compared with the fundamental flaw explained above: with no SSL, you cannot ensure that what runs on the client browser is your code.

Trying to handle password securely on a non-SSL Web site is akin to trying to perform brain surgery safely with only a tea spoon and a rusty crowbar. Just don't do it. If there is sensitive data that flows to the Web site (e.g. names and addresses), then you MUST apply reasonable protection mechanisms. If the data is not sensitive, then why would you need passwords ?

13

IMHO the random number generator is the least of your worries here. Since the code to invoke the enceyption is sent in the clear, it is trivial for someone to MITM the interaction.

If the service requires the level of security provided by encryption and is delivered by a website then it MUST use HTTPS (and ideally all the associated security stuff like secure+httponly cookies and HSTS).

The only way to get around this would be to write an HTML5 app (where the code is downloaded infrequently) - but even this has significant drawbacks.

  • 4
    Yes, but an HTML5 app would not be secure since there'd be no good way to authenticate, i.e. that your downloading the app from the the correct server and that it is unmodified. – Martijn Heemels Dec 16 '15 at 18:20
  • Yes, like I said it has significant drawbacks, and falls a LONG way short of a properly implemented HTTPS service, but its marginally better than trying to do this over HTTP. There are perfectly good ways to authenticate (but with no session protection). You seem to be comfortable with the authentication here on Stackexchange, Martijn :P – symcbean Dec 16 '15 at 21:24
  • 2
    Arguably it would be possible to host the HTML5 app elsewhere (on HTTPS) and carry out encrypted CORS AJAX to the site - but this is fraught with pitfalls even for an expert. You could get into orbit if you had a big enough ladder - but it's not a sensible way to solve the problem. – symcbean Dec 16 '15 at 21:35
10

The best solution, as has been stated, is to get a real web-hosting plan that allows https. This shouldn't be too expensive, in fact it should even be possible to find a free provider to provide this.

Failing that, what is your use case? It sounds like you have a set group of users in mind for your web site. If that is the case and you aren't just offering a subscription-based event notification service to random people on the internet, consider providing the basis for a 'secure' connection on a different channel.

It occurs to me that getting the code to their machine by another, reliable source (posting CD's via snail-mail and informing them via email, simply sending the software as an attachment to a digitally-signed email, etc.) allows you to pre-load the software with a cryptographic public key.

You can then negotiate a secure connection over an unsecure connection method (such as http) since the code determining whether the server has satisfactorily decrypted details encrypted with its public key lives on the client. A stream of 'plaintext' http application data is the result, with the wrinkle that the application data itself is encrypted.

This is a lot of trouble and a non-standard method. You run into problems with implementation since few people will have tried it to offer advice, and with security since few people have reviewed its reliability*.

The alternative channel may itself have security problems. Could mail be intercepted? Could scammers impersonate your organization and send their own, 'secure' version of your software? Are your users savvy enough to check digital signatures on emails you send? These are all concerns you'll need to consider and either accept as risks or attempt to mitigate with novel solutions, as you have less guidance around not only how to implement, but even what questions you need to ask (you'll need to ask more than just these three!).

When talking to the NGO management, consider outlining the situation in these terms:

  1. The latter method involves significant risk, and will end up costing them more of your time to implement than will simply paying for hosting - the program needs to be updated, especially if the server (or the server keypair) changes, and continually distributed to new users after the initial deployment.
  2. Doing nothing at all and using a password over http with addresses and names (and potentially email addresses) could be a public relations disaster if any information leaks (and it will), a significant risk. This is compounded by the fact that people re-use passwords and your bad practice could be linked to subsequent breaches.
  3. You have as such given the situation significant thought and are not just going to suggest the solution outlined in step 4 because 'everyone does it' (although, in the case where everyone does it because it is best practice, this is hardly a bad thing). Being able to propose the alternative (if convoluted and excessive) solution outlined in steps 1 & 2 is evidence of this due diligence being conducted.
  4. Based on this, https hosting with low (or no) ongoing cost is both the least costly AND least risky approach.

*Jonathan Gray goes into why you will run into issues coding a secure system in his answer, look at the section starting "TLS is also a much more intrinsic system"

  • 1
    If you're at the point where you're considering going through the trouble of pre-distributing encryption keys, I'd think much a better idea than to roll your own JS crypto would be to create your own SSL Certificate Authority (CA) and distribute the CA certificate to the clients. Then you'll have all the advantages of proper SSL, without having to pay for a certificate, but at the cost of pre-distribution and the burden of managing the CA properly. – Emil Lundberg Dec 18 '15 at 9:25
  • Good point, and assuming the reason it's claimed https can't be used on the provider is just certificate provisioning issues, this will be a lot simpler. Even if the provider outright blocks port 443, there's no reason example.com:80 won't work (unless they're doing packet inspection). I wonder if there are any sites backed by a big-name CA where you can host a root certificate with some checks around it that you could direct your clients to so they can download the public key? Probably not, it would compete with their certificate-selling business model. – Bruno Dec 22 '15 at 0:16
2

First replace your host.

Getting SSL certificates are easier then ever thanks to free CAs. LetsEncrypt, for example, offers free SSL/TLS Domain Validation certificates in an automated fashion provided you own the domain name. There is more explanation in StackzOfZtuff's answer on it's capabilities.

There are instructions on how to set it on their community site with FAQs and a help forum.

  • 1
    That does not answer the question since his hoster does not provide SSL/TLS support. Whether the certificate is free or not makes no difference. – Martijn Heemels Dec 16 '15 at 18:21
  • 8
    If his/her provider does not support TLS/SSL and it is for an NGO then as security stewards we need to encourage and help him/her find a hosting provider that does support security best practices. I am not the only one who suggested LetsEncrypt on this thread. LetsEncrypt is supported by many reputed organizations dedicated to privacy and security. We need to make users are aware of this as an option that is available to them. – ARau Dec 16 '15 at 18:30
  • Flagged for spam, as the asker isn't asking for a SSL/TLS certificate, and you give out a rather shady website that gives out "free" ssl/tsl certificates. – Ave Dec 16 '15 at 19:53
  • 24
    @ardaozkal While I agree this answer isn't particularly useful in this context, Let's Encrypt is far from "shady". It's very well known in the security community, and is backed by Mozilla, Facebook, Cisco, and the Electronic Frontier Foundation, among others. – Ajedi32 Dec 16 '15 at 20:15
  • 3
    @blownie55 I agree what we should advise the OP to find a better solution, as many are doing, however Let's Encrypt does nothing to help in that regard. Any cheap SSL certificate would do fine, or even a free one from StartSSL.com. The fact that Let's Encrypt is now available and is free is very nice but ultimately not the issue here. You're indeed not the only one who suggested it. That doesn't make you right, it makes the other one wrong as well. – Martijn Heemels Dec 17 '15 at 0:39
1

The problem with JS is random number generation (which is vital to the security of modern encryption). There are existing libraries available that help solve this, but you must make sure that library makes use of crypto.getRandomValues as-well as the ability to gain entropy from human input (such as mouse or keyboard activity). This is especially cumbersome for mobile devices, though, especially when considering the fact that the hardware itself is less capable of secure random number generation.

I would also like to add an additional point about RSA. You can only encrypt small amounts of data with it, and the data amount is relative to the keylength used. Not only that, but RSA is slow. If you require a decent amount of data or are making multiple requests to the server, I recommend encrypting a random key (CSPRNG) with JS on the client side using the public key of the server, and using that key for symmetrical encryption.

Edit: TLS is also a much more intrinsic system that works very hard to protect against all sorts of attacks. The only type of attack that TLS doesn't effectively protect against is a forced disconnection. Everything from server authentication to man-in-the-middle protection to protection against replay attacks are handled automatically by TLS at a layer not even seen by the average high-level programmer. In your situation you point out that you cannot utilize actual TLS/(SSL) connections, which is unfortunate. But I would like to make it clear that I highly recommend against any custom implementation designed to replace TLS.

1

Potentially as a last resort, as it is not going to be as good as end-to-end TLS... but you could perhaps put something like CloudFlare in front in order to at least have TLS to the client endpoint?

  • This works. I've once used Amazon Cloudfront "successfully" to route around the SSL overcharge prices of Heroku. But be aware that it gives users a false sense of security, since the traffic from the entry point to your server is unencrypted. – tanius Dec 19 '15 at 17:27
  • A theoretical possibility is configuring CloudFlare / Cloudfront to deliver the JavaScript files safely (via HTTPS) from an associated CDN rather than from your server, and everything else from your server using the JS clientside encryption. Practically, get a webspace with SSL, as mentioned … – tanius Dec 19 '15 at 17:30
1

Another option is to write a browser plugin, or a Tampermonkey script (to reduce cross-platform headaches), and have the JS code pre-delivered to the browser. I mention this purely as a measure of last resort.

The obvious downside is that your users are limited to using those computers that already have the plugin, or having to download it again every time they use a new device. It would also be difficult to use mobile devices with it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.