how to secure queries in meteor - javascript

The question is about duplicating queries in server/client in meteor.js.
here is a solution : https://www.discovermeteor.com/blog/query-constructors/. There , the author proposes a shared file between client and server to hold the queries.
I have readed the article and I find it interesting but I have a question. If you put your queries in a shared file, the client also has access and can modify them? The security problem is not solved?

Code on the client is by definition untrusted. Conversely, code on the server is trusted. Code that is used on both the client and the server (often by being placed under /lib but also by being imported into both) is untrusted when running from the client and trusted when running from the server. Remember that the client gets a copy of the code, the users don't actually have access to the original on disk or the other copy that is in server memory.
With Meteor's latency compensation, a shared method runs on the client first. The client state (in minimongo) immediately reflects the state achieved by running the method. Then the method runs again on the server. If the result is different in some way, then the client state is updated from the server with the correct data.
If you want to hide the method's logic from the server you can just not include it in your client code. You will forego latency compensation but you will keep your secrets secret! (ex: API keys, critical business logic). You can also have pure server code, such as startup scripts and cron jobs, that are never even invoked from the client.

In Meteor, nothing on the client can ever be trusted or considered safe. There is simply no way you can "hide" stuff on the client. If the browser can run it, a hacker can read it. And modify it.
Remember that queries on the client run on data on the client, and then the result of those queries is sent over a web-socket to/from the server. It is then the job of the server to do security/authorization/sanity checks on all data going out or coming in, to make sure only the data the client is authorized to view is sent, and only the modifications the client is allowed to do is actually done on the server DB.
The Discovermeteor blog you linked to is all about how to reduce code duplication between server and client, and still have flexibility between them. This has very little to do with security.
It does not really matter from a security point of view that the source code for the DB queries are readable on the client, because your server needs to do its security police job anyway. Otherwise you have an insecure app, even if the actual query source code is unknown.
An attacker can always look at the DDP protocol, it is almost as readable as a MongoDB query!

I think you're asking 2 different questions:
1) How do you ensure the security of a query?
2) How do you ensure the secrecy of a query?
WRT #1: Keeping a query in a shared lib file is secure because regardless of whether a client knows what query you're running, he won't be able to run it on the server and even if he changes it, that only alters the client copy, and doesn't affect the server's copy.
In the example you link to, note that the client is only able to change the limit field. He can't change the 'find' field. Even if he were to redefine the 'latestPost' function client-side to allow an additional parameter that gets added to the 'find' field, that function isn't redefined on the server-side so only the original definition will be used server-side (one point, however, is that in the example, the limit field isn't sanitized or checked for validity; a client could send text and cause an error).
So it would still be secure as you are limiting exactly which parts of the query constructor the client is allowed to change.
WRT #2: you're correct that this means the query won't be secret. The client will know exactly how you're querying, and with that info, may be able to deduce parts of your internal data structure.
Whether or not this is an issue is up to you, although I will say that in the security world, "security through obscurity" is considered bad practice: you should write your code such that even if all of your data structures, algorithms, and code is known, your data is still secure. That's why, for example, you can easily download the code for any encryption algorithm: the security doesn't depend on keeping the algorithm secret.

Related

Is it possible to sign/encrypt data on the client-side to ensure it was not manipulated by the user?

I save information in local storage and I want to make sure the user didn't replace the data or had fun with it.
The client receive an object, javascript analyse it, do it's thing and store some of it in the browser's local storage.
The data is sent to the server every 30 seconds and the server replies by another object, based on the previous data sent.
The process happens often so it would be preferable to avoid sending the server tons of data and make heavy query to verify the integrity.
I know Javascript in the client is prone to debugging, reverse engineering etc. But it would definitely add a layer of security so at least some people wouldn't bother. (Security through obscurity)
My initial thought was to make a checksum of the value I want to store, send it to the server and compare it to the checksum stored. If the result mismatch, dismiss the data on the client-side. I think it would be preferable to avoid storing in database and be able to check if it's legit with some function.
I would prefer if the data stored would look like a token (like a signed or encrypted base64 string) rather than raw data as it would leak some information about how the code works and may make it vulnerable.
Is there libraries or method of doing so that could help me in my journey?
Is it possible to sign/encrypt data on the client-side to ensure it was not manipulated by the user?
Short aswer - No, it is not possible.
Long answer - Any message authentication code (signature, hmac, ..) requires a secret value. As soons as you do the signing on the client side throuhg JavaScript, there is no way you can prevent the user to access the secret or modify data.
Take in account the user even may modify the application to change the client-side validation. Long story short - never trust user's input, you have to always validate data on the server side.
Suggestion - you may send the data to a server service and the server could sign/hmac the data. The same way you could validate the data integrity.
But it would definitely add a layer of security so at least some people wouldn't bother. (Security through obscurity)
In my opinion - it doesn't matter much. If the user doesn't care, he won't modify the data. If you have a dedicted user, no level of obfuscation will stop him.
I would prefer if the data stored would look like a token (like a signed or encrypted base64 string)
Nothing prevents you to do so.

API calls from JavaScript to backend: Ensuring legitimacy without server-side code

I want to create a Javascript widget that my users can put on their websites.
The widget is capable of creating audio, which in turn costs my users' money.
For the sake of illustration, let's say that every time a widget, placed on my user's site, is loaded by anyone on the internet (i.e. my users' users), I bill my user $1.
The widget is a Javascript code wrapped around an HTML audio player. The JS code makes a request to my backend API every time it is loaded, and upon receiving the response from my backend API, the player is constructed.
Diagram:
My concern is malicious usage by people who are not my users.
Let's say someone takes the widget's source code they found on a website that belongs to one of my users, and they put it on their site. They will, therefore, use my service but not pay for it. Instead, my actual user will pay for it (assuming I use a public API key as a way of distinguishing my users).
Usually, this is prevented by having a server-side library be responsible for any usages that might spend money. For example, I use Pusher as my WebSockets IaaS, and whenever I want to publish messages, I have to do it server-side, using their PHP SDK, with both private and public API keys.
In my use case, it's mandatory not to have a server-side library.
Question: how do I make sure that API requests I receive are legitimate?
I considered using the hostname where the widget is placed as a legitimacy measure. During the widget set-up, I could ask my users to whitelist certain (sub)domains and reject all requests that don't match the criteria, but this could be easily spoofed by, for example, a custom local domain or a CURL-crafted request.
I understand this may not be possible.
It seems like what you're asking is closely related to the topic of client side encryption. In most cases, the answer would be no, its not possible. However, in this case, it may be possible to implement something along the lines of the following. If you can get your clients to install a plugin (which you would build), you could encrypt your JS code after finishing it, and have your server serve this encrypted file. Normally, where this falls short, is that if you're sending an encrypted file, there needs to be a way for the client to decrypt it. This would require you to also serve an unecrypted JS file which would do the decoding, but by serving the unencrypted decoder you undo any security gained by encrypting your main JS file (the decryption file could be easily used to reverse engineer your encryption method/ just straight up run for people other than your intended users). Now, this is where having those API users (and the ability to communicate with them through means outside of server-client connections) comes in handy. If you build a decryption plugin, and give it to the API users (you could issue a unique decryption key for each user, but without server access implementing unique user keys would be very difficult/impossible), the plugin could then decrypt your served file in their browser, essentially guaranteeing that only users you have given the 'key' to can access your software. However, this approach has a few caveats. It implies that you trust your users enough that they wouldn't distribute the plugin (it would be against their intrest to distribute it anyway, as it could lead to higher chargers if people impersonate them). There are also probably a couple of other security concerns with this approach, however, I can't think of them right now. If any come to mind, I'll edit this post and add them.
apparently, I don't have enough reputation to comment yet, hence the post...
But in response to your post, I think that method seems much better than the one I suggested; I didn't realize you could control the API's response to the server.
I don't quite understand which of the following you mean:
a) Send a JS file to the user, with the sole purpose of determining if the player should also be sent (ie upon arriving, it pings the server with the client's API key/ url) and then the server would serve the file (in which case your approach seems safe to me, but others may find security problems with it).
or
b) Send a file with the JS and the audio player, which upon arriving, determines if the URL and API key are correct, and then allows the audio player to function normally (sending the API key to the server to track usage, not as a security feature).
If using option b, this would not improve security. If your code relies on security that runs on the client-side, and the security system was sent by the same means as the code, then almost without exception, the system designed is flawed and inherently unsafe.
I hope this makes helps, and if you disagree / have more questions, feel free to comment!
How about sending the following parameters from JavaScript widget to API backend:
Public API key (e.g. bbbe3b259f881cfc796f468619eb9d)
Current URL (e.g. https://example.com/articles/chiang-mai-thailand-january-2016-june-2016)
I will use the API key as a way of distinguishing my user and the current URL as a way of knowing which audio file to create (my widget will create an audio file based on the URL).
Furthermore, and this is crucial, I will have a user whitelist their domains and subdomains on my central site, where my users will get their widget code.
This is the same as what FB does for their integrations:
So if for example, my backend API receives the aforementioned sample URL, and the user has set up the widget to only allow URLs that belong to foo.com and bar.baz.com, I will reject the audio creation process and display an error.
Do you see any issues with this approach?

How to verify that Javascript on client has not been altered

Is there any way to verify that the javascript file as loaded (and potentially altered) by the client has not been tampered with by a malicious user?
I'm thinking of something like this:
1) Computing a checksum and sending this for the server for verification
2) Sending the file as it is in browser memory back to the server for comparison/checksumming.
Is anything like this possible? How can you verify the integrity of the executed javascript given a known-good copy on the server?
tl;dr No
As a malicious use can easily tamper with the data getting sent to the server there's no way of securely verifying that the Javascript has not been altered. Even if you did hashsum calculations there's no way of making sure that the user is not modifying that hashsum before sending it to the server.
You simply have to find other means to make your solution secured. Usually this mean that you've to run your business logic on the backend rather than on the client.
I don't think there is a good solution for this, simply because even your checks to the server could be manipulated client side, I could easily change the checksum to the original one and send that one to your server.
Keep the validation on the server, never store or use key variables / data in the browser. You should use JavaScript to process the received data and interact in the UI. The only thing people could do is change the values shown to the eye.

Server overload ... with requests? How do I efficiently program server-client wise

SO, I have a server with MySQL database in it, and a client (browser) that retrieves data from the server and displays to the user.
I'm struggling over whether I should let client get all the data he needs from a MySQL server (using PHP), and let client to do all querying, adding, updating to the data with JavaScript or other related library, and send it back to the server for the server to update his data; OR
whether I should let client send requests (query, add, update, etc) to the server with relevant parameters for server to handle the user's data with, say, MySQL commands.
I think first way could relief the server because all the work is done by the clients' computer, and not by the server, but would be hard for me to learn or make a library that does all the querying and stuff that can otherwise be done with MySQL commands which I find easier to work with at this moment.
And I think the second way would be easier for me, because I can just use PHP and MySQL to perform whatever server needs to do for client, but it makes me think that it would load server with too many repetitive work for each client if there were too many clients.
Which method is better?
At this moment, I'm the only client and server is run on the same computer, so there won't be too much load of commands that server would need to run, but I want to know which method is most canonical and efficient security, efficiency, etc wise.
Both solutions have their pros and cons. If you have a huge set of data, you don't want to dump it all to the client, especially if they only need to view or modify a fraction of it. If any of your data needs to be protected against unwanted change (like a user increasing their access level, credit, etc) you can't place the logic on the client since that will be easy to hack. If neither is a concern, client-side logic may indeed take a lot of load off your database server.
There are client-side frameworks like Angular and React that make working with data easier, although they too have a learning curve. Check if they fit your needs.

javascript global variables - protection

I am using some global variables on a web application, built on Html/Javascript. I am using these variables across pages (or portions of them), and sometimes they are used as post data for ajax calls. My question is: how secure is this? surely i can set different values for these variables (using a console for example) and then, the calls that rely on this var are made. Imagine the user sets some Id that corresponds to something that he even doesn't have access to..
How should this be done?
Thanks in advance
There is nothing different about this from any web application, from a point of view of security.
Anything sent from the browser must be treated as untrusted by the server. This includes URL parameters, form post data, cookies, http headers and anything controlled by javascript. All these items can be manipulated by an attacker.
Essentially, it doesn't matter what the values are in the client, you only need to worry about them when they hit your server in the form of a new HTTP request (this includes XHR). Until that point, variables with bad values can't do any damage.
Ensure your server can correctly authenticate the current user and only allow them access to data and actions that they are authorised to perform. Ensure that all data received from the browser is checked to be correct (if known) or of the correct datatype and within expected limits, rejecting the data and aborting the action if it is not.
if you use jquery, you can use
$.data()
With this, you can associate the data with an element, thus a unauthorized user will not be able to access it
Javascript has runtime type identification (everything is a var like visual basic), its a loosely typed language.
Javascript has its own security model though
User cannot access files (r/write)
It cannot access or look at user location, files, open windows without demand etc
It is not possible to protect the source of your javascript file either or even pwd protecting it as this is better done server side.
Even encryption or decryption doesnt work because somehow you need to tell your users the key
Worse, JavaScript can self-modify at run-time - and often does. That means that the security threat may not be in the syntax or the code when it's delivered to the client, but it might appear once the script is executed.
There is no JavaScript proxy that parses and rejects malicious script, no solution that proactively scans JavaScript for code-based exploits, no external answer to the problem. That means we have to rely on the browser developers to not only write a good browser with all the bells and whistles we like, but for security, as well.

Categories