I am implementing a so called "single page app" which accepts JSON as input. That also means that all HTML is rendered in the browser, also all templates (am using knockout) are seemingly unaffected by user input, in the sense that the template is not constructed dynamically by the backend but rather embedded statically in the client. In other words, I do NOT anything like this:
echo '<input type="text" value="$var">'
So all rendering of user content essentially boils down to these JS methods:
document.createTextNode(userVar); // for displaying static text
inputElement.value = userVar; // for populating input fields
document.title = userVar; // some user input can be reflected in the doc title
window.history.pushState = ... // no user input is set here directly, but there are URIs where this could be set using an outside link
So now the question would be: are these methods all 100% XSS safe? Or would there still be any way to trigger a XSS attack - and if "yes", how could this be done?
I believe those four functions are safe. The document.createTextElement method appears to be safe, and none of the other methods are capable of adding objects to the DOM.
In order to launch an XSS attack, an attacker must be able to either hijack an existing script to run arbitrary code (why eval is evil) or insert their own scripts through vectors such as <script> tags. Since you are using methods that aren't capable of adding elements to the DOM, nor are they capable of manipulating event handlers, I would think that you are safe.
We would also need to be able to see more of your backend code to make that call, however, but on the frontend it looks okay.
Whether or not your JavaScript is susceptible to Cross-Site Scripting (XSS) is one question, whether it is secure at all is another. The idea with XSS is that the attacker puts code into your system, which is then run by another user, it might redirect them to another (potentially malicious) site for example.
If you're not storing the input data to your system, and then displaying it to another user, then you're safe from XSS. The user can only attack themselves, which is pointless in my opinion.
If however you are storing the input data to your system, then you have a potential problem (hard to know without knowledge of your back-end). But whatever you submit via JavaScript, wherever you send it, the back-end has to process (verify and validate) it before storing to ensure it's not malicious.
Bottom line is don't rely on JavaScript. Whether your script is 10 lines, or 1,000,000 lines it can all be manipulated via the front-end because it runs client side. You can try this yourself in Google Chrome using the inspector.
Related
I am working on a Java project. In it, we want to enable an end-user to define variables which are calculated based on a set of given variables of primitive types or strings. At some point, all given variables are set to specific values, and then the calculations should be carried out. All resulting calculated variables must then be sent to Java.
I am in the process of evaluating ways for the end-user to define his calculations. The (current) idea is to let him write JavaScript and let that code be interpreted/executed inside the Java program. I know of two ways for this to be done: Either use the javax.scripting API or GraalVM/Truffle. In both, we would do it like this:
The given variables are given into the script. In javax.scripting via ScriptEngine.put, in Graal/Truffle via Value.putMember.
The end-user can define variables in the global context (whose names must not collide with the ones coming from Java). How he sets their values is up to him - he can set them directly (to a constant, to one of the given variables, to the sum of some of them ...) or define objects and functions and set the values by calling those.
When the time comes where the given variables have a fixed value, the script is executed.
All variables that were defined in the global context by the script will be sent to Java. In javax.scripting via ScriptEngine.get, in Graal/Truffle via Value.getMember.
NOTE: We would not grant the script access to any Java classes or methods. In javax.scripting via check if the script contains the string Java.type (and disallow such a script), in Graal/Truffle via using the default Context (which has allowAllAccess=false).
The internet is full of hints and tips regarding JavaScript security issues and how to avoid them. On the one hand, I have the feeling that none of them apply here (explanation below). On the other hand, I don't know JavaScript well - I have never used it for anything else than pure, side-effect-free calculations.
So I am looking for some guidance here: What kind of security issues could be present in this scenario?
Why I cannot see any security issues in this scenario:
This is pure JavaScript. It does not even allow creating Blobs (which are part of WebAPI, not JavaScript) which could be used to e.g. create a file on disk. I understand that JavaScript does not contain any functionality to escape its sandbox (like file access, threads, streams...), it is merely able to manipulate the data that is given into its sandbox. See this part of https://262.ecma-international.org/11.0/#sec-overview:
ECMAScript is an object-oriented programming language for performing
computations and manipulating computational objects within a host
environment. ECMAScript as defined here is not intended to be
computationally self-sufficient; indeed, there are no provisions in
this specification for input of external data or output of computed
results. Instead, it is expected that the computational environment of
an ECMAScript program will provide not only the objects and other
facilities described in this specification but also certain
environment-specific objects, whose description and behaviour are
beyond the scope of this specification except to indicate that they
may provide certain properties that can be accessed and certain
functions that can be called from an ECMAScript program.
The sandbox in our scenario only gets some harmless toys (i.e. given variables of primitive types or strings) put into it, and after the child has played with them (the script has run), the resulting buildings (user-defined variables) are taken out of it to preserve them (used inside Java program).
(1) Code running in a virtual machine might be able to escape. Even for well known JS implementations such as V8 this commonly happens. By running untrusted code on your server, whenever such a vulnerability becomes known, you are vulnerable. You should definitely prepare for that, do a risk assessment, e.g. which other data is accessible on the (virtual) machine the engine runs on (other customers data?, secrets?), and additionally harden your infrastructure against that.
(2) Does it halt? What happens if a customer runs while(true); ? Does that crash your server? One can defend against that by killing the execution after a certain timeout (don't try to validate the code, this will never work reliably).
(3) Are the resources used limited (memory)? With a = ""; while(true) a += "memory"; one can easily allocate a lot of memory, with negative impact on other programs. One should make sure that also the memory usage is limited in such a way that the program is killed before resources are exhausted.
Just some thoughts. You're essentially asking if you can trust your sandbox/vitual machine, for that you should either assume that you're using a good one or the only way to be really sure is to read through all its source code yourself. If you choose a trusted and well known sandbox, I'd guess you can just trust it (javascript shouldn't be able to affect file system stuff outside of it).
On the other hand why aren't you just doing all this calculations client side and then sending the result to your backend, it seems like a lot of setup just to be able to run javascript server side. If the argument for this is "not cheating" or something similar, then you can't avoid that even if your code is sent to the server (you have no idea who's sending you that javascript). In my opinion doing this setup just to run it server side doesn't make sense, just run it client side.
If you do need to use it server side then you need to consider if your java is running with root permissions (in which case it will likely also invoke the sandbox with root permissions). On my setup my nodejs is executing under ~/home so even if a worst case happens and someone manages to delete everything the worst they can do is wipe out the home directory. If you're running javascript server side then I'd strongly suggest at the very least never do so under root. It shouldn't be able to do anything outside that sandbox but at least then even in the worst case it can't wipe out your server.
Something else I'd consider (since I have no idea what your sandbox allows or limits) is whether you can request and make API calls with javascript in that sandbox (or anything similar), because if it's running under root and allows that it would give someone root access to your infrastructure (your infrastructure thinking it's your server making requests when it's actually malicious JS code).
You could also make a mistake or start up your VM with an incorrect argument or missing config option and it suddenly allows a vulnerability without you being aware of it, so you'll have to make sure you're setting it up correctly.
Something else is that if you ever store that JS in some database, instead of just executing it, then you have to make sure that it's not made directly available to any other users without checking it otherwise you'd have XSS happening. For example you build an app for "coding tests" and store the result of their test in a database, then you want to show that result to a potential employer, if you just directly display that result to them you'll execute malicious code in their browser.
But I don't really see a reason why you should care about any of this, just run it client side.
I'm an Angular noob. In an app I have taken over there is an object in the scope that defines the role of the current user (e.g. user.role=REGULAR).
Is there a way to keep a user from opening firebug and changing user.role=ADMIN?
For example, I have seen code that shows a tab based on a value in a scope, but I'm not sure how to keep a user from changing that value (and getting access to the tab). Is there a pattern to deal with this? Does everything access-related need to come directly from a web service/protected remote location?
There is no way to do this. Your design has a fundamental issue; it relies on client side validation.
You can never ever ever ever ever trust anything coming from the client. Anything that you truly want validated or authenticated must be done on the server side, particularly security related matters.
The most important rule is that once it leaves the server and hits the client, its out of your control. Assume its compromised, assume its not trust-worthy, and assume you have to check everything.
In your case, if a user is not an admin don't even provide them with admin options.
Well, you can try to hide the object inside of a closure or use Object.freeze in browsers that support it, however there is no getting around the fact that the code is being sent to and executed on the client. Even if there was a foolproof way of preventing modification ( which there isn't ), the client could have modified the payload in Fiddler or something before it reached the browser.
With that in mind, you cannot trust anything on the client for access/authorization; you must verify this on the server or you'll have security holes/risks.
I don't understand how does ECMAScript works. Check on MSDN and other forum it didnt tell us which version or values equal to javascrpt.
if (!Request.Browser.JavaScript)
//Do Something.
However, I was given a warning of obsolute and recommend me to use ECMAScript instead.
System.Web.HttpBrowserCapabilities myBrowserCaps = Request.Browser;
if (((System.Web.Configuration.HttpCapabilitiesBase)myBrowserCaps).EcmaScriptVersion.Major < 1)
//Does not have Javascript. Do something.
However, I tried both on/off my javascript. Somehow the function was not fired. I suspect certain values belong to javascript. However, I cant find anything related to value == javascript.
I understand I could a Then perform a redirect using meta tag. But I would like all these code to perform at the server.
First of all, see Should I bother to develop for JavaScript disabled? / How important is graceful degradation of JavaScript? .
Then, client-side Javascript only exists in the client and if it's off, no client-side logic will fire to check anything explicitly. So you cannot know it until the client sends at least one reply from your page (be it a GET/POST query or an XMLHTTPRequest) - i.e. only after the second request from that very user, generated by the very page you sent them, which may never occur if they just lurk around, even if you make every link on your page a form reply - they may use URLs from an external source. A CodeProject article linked from Check if javascript is disabled? is one example of such approach.
For this reason (and to avoid effort duplication to make both script and noscript versions - the practice that saw some use in the past), the best practice appears to have become making pages and frameworks JavaScript-agnostic and just warning the user with <noscript> that the page may not be fully functional if it's relevant.
E.g. Sharepoint does just that - with JS disabled, a warning appears on top while on the page, there are e.g. no scrollbars and editing is disabled completely. Which leads to conclusion that ASP.NET controls (which SP makes heavy use of) weren't designed to be functional beyond basic display with JS disabled in the first place.
I am making a website and I want to use the following design:
Each time a user clicks a link an ajax request is sent.
The reply contains 2 fields:
the HTML that replaces the content area
A JavaScript to be evaluated (JavaScript behaviors attached to objects withing the new HTML content)
Does this use of JavaScript eval() have any downsides?
Edit
The JavaScript that is to be evaluated is varied - it's not something that can be sensibly expressed with a single function taking different arguments.
Cross-site scripting was mentioned, but I don't see how this use is different from a user visiting a new JavaScript-containing page.
This mainly depends upon how the javascript to be evaluated is generated. Any use of eval is potentially subject to cross site scripting, but only if the js is generated by something that a user can control. If the server is returning a static js, that's no more inherently bad than the use of js anywhere else.
Can't think of any, although my imagination may be a bit lacking. ) Besides, isn't JSONP something of the same method?
I'm working on a webapp to teach programming concepts. Webpages have some text about a programming concept, then let the user type in javascript code into a text editor window to try to answer a programming problem. When the user clicks "submit", I analyse the text they've typed to see if they have solved the problem. For example, I ask them to "write a function named f that adds three to its argument".
Here's what I'm doing to analyse the user's text:
Run JSLint on the text with strict settings, in particular without assuming browser or console functions.
If there are any errors, show the errors and stop.
eval(usertext);
Loop through conditions for passing the assignment, eval(condition). An example condition is "f(1)===4". Conditions come from trusted source.
Show passing/failing conditions.
My questions: is this good enough to prevent security problems? What else can I do to be paranoid? Is there a better way to do what I want?
In case it is relevant my application is on Google App Engine with Python backend, uses JQuery, has individual user accounts.
So from what I can tell if you are eval'ing a user's input only for them, this isn't a security problem. Only if their input is eval'd for other users you have a problem.
Eval'ing a user's input is no worse than them viewing source, looking at HTTP headers, using Firebug to inspect JavaScript objects, etc. They already have access to everything.
That being said if you do need to secure their code, check out Google Caja http://code.google.com/p/google-caja/
This is a trick question. There is no secure way to eval() user's code on your website.
Not clear if the eval() occurs on client or server side. For client side:
I think it's possible to eval safely in an well configured iframe (https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/)
This should be 100% safe, but needs a couple of libraries and has some limitations (no es6 support): https://github.com/NeilFraser/JS-Interpreter
There are lighter alternatives but not 100% safe like https://github.com/commenthol/safer-eval.
Alternatively, I think something similar can be implemented manually wrapping code in a with statement, overriding this, globals and arguments. Although it will never be 100% safe maybe is viable in your case.
It can't be done. Browsers offer no API to web pages to restrict what sort of code can be executed within a given context.
However, that might not matter. If you don't use any cookies whatsoever on your website, then executing arbitrary Javascript may not be a problem. After all, if there is no concept of authentication, then there's no problem with forging requests. Additionally, if you can confirm that the user meant to execute the script he/she sent, then you should also be protected from attackers, e.g., if you will only run script typed onto the page and never script submitted via GET or POST data, or if you include some kind of unique token with those requests to confirm that the request originated with your website.
Still, the answer to the core question is that it pretty much is that it can't be done, and that user input can never be trusted. Sorry :/
Your biggest issue will always be preventing infinite loops for occurring in user-provided code. You may be able to hide "private" references by running eval in the right context, e.g.:
let userInput = getUserInput();
setTimeout(() => {
let window = null;
let global = null;
let this = null;
// ... set any additional references to `null`
eval(userInput);
}, 0);
And you could wrap the above code in a try/catch to prevent syntax and logic errors from crashing outside of the controlled eval scope, but you will (provably) never be able to detect whether incoming user input defines an infinite loop that will tie up javascript's single thread, rendering its runtime context completely stalled. The only solution to a problem like this is to define your own javascript interpreter, use it to process the user's input, and provide a mechanism to limit the number of steps your javascript interpreter is willing to take. That would be a lot of trouble!