Okay, the title of this topic is really stupid - but I am not able to sum it up in a better way than that. So here is more detailed version of my problem:
I am creating a small JavaScript library that enables developers to send strings on custom events to a dedicated server (url defined in the library). Lets say the library is called "testLib", the developer that uses this library could write something like this:
function success() {
testLib.send("Everything OK");
}
So everytime this success function is called, a REST call (POST-request) is made to the server that is definded inside the library. So far, thats no problem.
But the ugly thing is that everyone with firebug or similar could call these "testLib.send()" method too. Thats really ugly, because the hole sense behind this library is to track only the events that the developer has defined. Of course, the server will take care of the basic validation (origin check, API key,..), but still: One could start firebug and just call the "testLib.send" method.
Is there any chance to build an authorization mechanism that prevent the "firebug user" from sending rest calls via the predefined library methods?
Nothing practical.
The library runs on the client's computer. You have no control over that. They can edit the JS to their heart's content. They can bypass it entirely and send hand-crafted HTTP requests if they want (or write a quick script to bomb the server with requests).
Any real protection you implement has to be on the server.
Writing Javascript is like writing open source. FireBug is but one of the plugins which can get into your script, modify it on the fly, invoke methods, access variables, etc. In fact, you don't have to go that far: The Javascript console in most browsers contains a quick eval input box. Because Javascript is an interpreter, anyone can get in and do as they wish.
You have two options which might make it a tad more difficult (though certainly NOT impassable):
1) Obfuscation and/or packing the script, when you are done - though most obfuscators can easily be bypassed
2) Having your methods check who called them - have a look at arguments.callee.caller for that. That said, this might run into problem in strict mode.
Your best bet is to repeat any validation in the server side, as you say. If the server side validation fails - this actually tells you something: Someone deliberately bypassed your Javascript, and you can deal with him accordingly.
Hope this helps
TG
Authenticating users
If you application authenticates a user when the page loads, then every request from the client side will come along with authentication cookie so basically you will be able to detect who the sender is.
Obfuscation and private closures
But if you'd like to prevent programmatic access to that particular function that your best bet is function closure to make that function private and inaccessible and some code obfuscation that prevents people from plainly rewriting the whole stuff. One great obfuscation is the Javascript packer with Base62 enabled.
But this kind of things will of course obfuscate your library, but publicly accessible functions would still be accessible.
Preventing anonymous users
However. If you'd like anonymous users to prevent from sending stuff to your server you can't do that really, but you can identify unauthorised requests, by having your functions to require some sort of a registration key that your developers (real users) would have, but anons wouldn't.
And maybe some other resources found on Google may help just a well. Just to scratch the surface. XHR for instance allows users to send username and password to authenticate the request which may be exactly what you're after. But you should know better since you have the library design not us.
No. Because javascript runs on the client side, there's nothing you can do to prevent someone from reading what the client is executing and executing it themselves. There are things you can do to obfuscate your calls, but this is security through obscurity - and shouldn't be relied on. If you want to make sure that ONLY the developer is making calls to your API, they would need to do it on the server side.
Related
I am working on a React-based web app that uses Tensorflow.js to run an AI model in realtime on the client in the browser. I've trained this AI model from scratch and I'd like to protect it from being intercepted and used in other projects. Are there any protections available to do this (obfuscation, DRM, etc.)?
From a business perspective, I'd only like the model to work on my web app, nowhere else.
The discussions (1 2 3) I've been able to find on this are more geared toward native apps, not web apps.
Here is an example open source web app that uses Tensorflow.js. These weights are an example of what I would like to protect in my app.
Client-side code obfuscation will never fully prevent it. Use a server instead.
Obfuscation
If your client-side application contains the model, then the user will be able to somehow extract it. You can make it harder for the user, but it will always be possible. Some techniques to make it harder are:
Obfuscating your code: That way the user will not be able to read your code and comments easily. Depending on your build tools, this might already be done for you when you produce a "production ready" build.
Obfuscating the library and its public API: Even if your code is obfuscated, the user might still be able to guess what is going on by seeing the public API calls of the library. Example: It would be rather easy to set a break point at the model.predict function and debug your code from there on. By also obfuscating libraries and their API, this will become harder.
Put "special checks" in your code: You could also check if the page the code is running on is your page (e.g. if the domain matches), etc. You also want to obfuscate this code as well.
Even if your code is perfectly obfuscated and well protected, your client-side code still contains your model somewhere. With these methods it will always be possible to somehow extract your model.
Server-side approach
To make it impossible to get your model, you need a different approach. Only put your "dumb logic" on the client. Exclude the part of code that you want to protect. Instead you offer a API on your server that executes the "protected part" of your code.
This way, instead of running model.predict on the client-side, you would make an AJAX request to your backend (with the parameters) and then return the results. That way the user only sees the input and the output and cannot extract the model itself.
Keep in mind that this means a lot more work, as you not only have to write the code for your client-side application but also for your server-side application, including the API. Depending on how your application looks like (e.g.: does it have a login?), this might be a lot more code.
Another way you can protect your model is to split the model into more than one blocks. Put some blocks at server side and some at client side. This method may also introduce a lot of engineering work, but once you do that you can trade off the computation loading and network latency between the server and client. Users can only get some model blocks which is useless without cooperating with server side blocks.
We have an app that sits behind a firewall and behind a CAS authentication layer. It has a feature that allows users with a special role to customize the way the app works by writing JavaScript functions that get inserted into the application at runtime, and which can be fired by events such as button clicks and page load and the like. (The JS is not "eval"'d - it is written into the page server-side.)
Needless to say, this feature raises security concerns!
Are there recommendations beyond what's being done already to secure this, that is beyond a) firewall, b) robust authentication and c) authorization.
EDIT:
In response to questions in comments:
1. Does the injected code become part of the application, or it is executed as an independent application (separated context)?
Yes, it becomes a part of the application. It currently gets inserted, server-side, into a script tag.
Does inserted JavaScript run on clients' browsers other than the original writer?
Yes. It gets persisted, and then gets inserted into all future requests.
(The application can be thought of as an "engine" for building custom applications against a generic backend data store which is accessed by RESTful calls. Each custom application can have its own set of custom these JavaScripts)
You really shouldn't just accept arbitrary JavaScript. Ideally, what should happen is that you tokenize whatever JavaScript is sent and ensure that every token is valid JavaScript, first and foremost (this should apply in all below scenarios).
After that, you should verify that whatever JavaScript is sent does not access sensitive information.
That last part may be extremely difficult or even impossible to verify in obfuscated code, and you may need to consider that no matter how much verification you do, this is an inherently unsafe practice. As long as you understand that, below are some suggestions for making this process a little safer than it normally is:
As #FDavidov has mentioned, you could also restrict the JavaScript from running as part of the application and sandbox it in a separate context much like Stack Snippets do.
Another option is to restrict the JavaScript to a predefined whitelist of functions (some of which you may have implemented) and globals. Do not allow it to interact directly with DOM or globals except of course primitives, control flow, and user-defined function definitions. This method does have some success depending on how robustly enforced the whitelist is. Here is an example that uses this method in combination with the method below.
Alternatively, if this is possible with what you had in mind, do not allow the code to run on anyone's machine other than the original author of the code. This would basically be moving a Userscript-like functionality into the application proper (which I honestly don't see the point), but it would definitely be safer than allowing it to run on any client's browser.
I wanna know, is there a way to compress javascript with a method that cannot be easily uncompressed by another?
I have used some tools like jscompress and other products. They're nice and useful, but they provide methods to uncompress/decode script too. The problem is other programmer or maybe hacker, can easily uncompress my script, the impact is my js ajax link, variable can be seen by the hacker. You know that what happen if they found our link. Maybe post direct value via ajax etc.
There is not a way to do this in client side javascript, it is inherently insecure. You should be using a call on your server to hide your API key.
FAQs from the w3:
http://www.w3.org/Security/faq/wwwsf2.html
If by your question you mean that you do not want the variables and Ajax links in your script to even be accessed by others ever, then you are talking about encryption, not just compression.
If the code was truly encrypted so that the Ajax links were not recoverable, the browser could not decrypt and therefore not even execute the script.
Obfuscators will make your code fairly illegible, but you are not going to be able to hide destination URLs in Ajax calls from hackers. All one needs to do is look at the browser's developer tools and watch the network calls.
It's important to design your application with the assumption that users and hackers are able to see all the JavaScript. If you can keep it secure under these conditions, that's ideal.
So if the question is just about making your code hard to read, obfuscate. But the kind of security you seem to be asking about needs to be done server side.
I'm modifying an existing web application that features the ability to administrate users who are able to log into the system. When modifying a user's details via a dialog, update data is sent to the server via AJAX. A few lines of javascript to then update the current page to reflect these changes is returned with the intention of being executed. This strikes me as poor form - isn't executing remotely acquired JS dangerous?
If I were to modify this, I would have the AJAX call that sends the updated information then call another function that gets the latest data from the server via AJAX (or just refresh the page, if I am feeling lazy). Is there any advantage (mainly security, but from an architectural perspective as well) to making this change, or am I being anal?
Assuming we're talking about eval used on non-json.
People will tell you all sorts of things, most of it has some basis in reality. I'd say one reason that is really understandable: it will make the code a nightmare to maintain and it will be very hard to trace bugs.
There are security concerns, a lot of people like to jump on the "javascript is the clients problem" bandwagon. I say if it comes from your site, it's your problem too.
In the end, there is no good reason I can think of to eval javascript from the server. Pass data from the server, and write the javascript on the client-side to react to that data.
All JS executed by the browser is remotely acquired.
The server that returned the JS/JSON via AJAX is the same server that returned the HTML that did the AJAX call in the first place.
It if's possible to do something bad, it can be done whether you eval the result of the AJAX call or not.
Personally, I don't see the issue. Sure, people say things such as "It allows code execution client-side" however if the potential attacker is able to affect that, then that's your problem - not the ability to modify the code.
Seriously, I think you have far more pressing concerns than that. I'd personally spend that 10 minutes or so reviewing your code and looking for flaws instead of working on an alternative to eval(). I think it'll improve your security a fair bit more.
Mike Samuel mentions MITM. I don't see why. If you're susceptible to a MITM attack then chances are that code can be injected straight into the initial HTML page (again, sure, slightly higher risk but is it really worth worrying about? Your choice.)
If a trusted developer wrote all of it and you protect it the way you do the rest of your HTML page, then no.
But even if it is JavaScript written by trusted developers, if it is served over HTTP, then an attacker can modify it in-flight because HTTP over free wireless is often susceptible to MITM.
This can be used to effectively install a keylogger in the current browser window to steal user passwords, redirect them to phishing pages, etc.
The attack might work like this:
Web page does a GET to http://example.com/foo.js.
Attacker modifies foo.js mid-flight to add JavaScript that does window.addEventListener("keypress", /* a keylogger that sends all keys to evil.com cross domain by image loading tricks */)
Browser loads modified JavaScript.
User enters a password in an <input type=password>.
Evil wins.
Since HTTPS (assuming no mixed content) is not susceptible to MITM, it is not vulnerable to this attack.
You probably don't want to just call another function after you send the data update because you could then display information that isn't true if an update fails. At least with the current model, your service can tailor the javascript based on whether or not the update was successful. You may want to consider having the service just return a true/false and have the call back function handle the updating of the UI.
Sort answer: Yes
Long answer: You should just send data for both security reasons and to keep your implementations separate.
Improperly sanitized user-submitted content or advertisements could inject code and get it run. Granted, this would have to be a targeted attack, but hey maybe you're working for a startup that's going to be the next Google or a forum system that's going to be the next vBulliten. Even if you have 10 users, security holes are still holes and are still bad for you and your users. Also, bad security advice left lying around SO will lead others to make bad decisions.
Do you really want to have to make sure the code you generate on the fly and send to the client is correct in all possible cases? What if someone else works on just one half of the system? Are they going to know every variable name to avoid stomping on? Just sending data is the best way to keep a 'small' change in your client/server communication from breaking everything in ways that aren't obvious and will take forever to debug.
I’ve always been having this problem in mind and always went with the easier more solution of doing it on the server. However, I decided I can ask more people about it, may be one of the enlightened can help me with a reliable solution.
Problem: you’re developing a web application that servers many users. Part of the features you offer involves calling an external API. That call is done for each user. The call can be made by either your server or the browser’s JavaScript. In either cases you persist the result of processing the data from the API call in the server’s database. I would like to offload calling the API and processing the results to the browser’s JavaScript and after it finishes it will callback the server with the data to persist. The problem that I see with this approach is that anyone can modify that JavaScript’s behavior (how easy is that thnx to firebug and its likes) to persist malicious/incorrect data on the server.
How can I - the server - trust that the data coming to me from JavaScript - following the previous scenario - is correct and not altered?
The simple answer is you can't, JavaScript is the least secure mechanism in the pipeline - the easiest to manipulate. If you want it to be secure, you should never rely on JavaScript for it.
Think of it in a more general sense: you can only secure an environment you at least somewhat control...you have no control over the browser, the JavaScript engine, or the user manipulating it.
Always validate server-side, always, always, always.
If you want to create some data on server A, give it to a client, and have that client pass it to server B verbatim, then you simply need to include an anti-tamper hash with it. Server A and B share a secret which they use as salt. As the client doesn't know this salt, it is unable to fabricate authentic data for itself.
Note that on its own, this technique only gives a strong degree of confidence that server A originated the data. There are other vulnerabilities you may need to consider, such as replay attacks of old data etc.