How to avoid using JavaScript eval() in user-defined function - javascript

I'm trying to make a generic table-top RPG helper web app. It has to be generic because Wizards of the Coast is very protective of their copyrights. So, in order to avoid cease-and-desists, the system has to be capable of loading arbitrary rules. That said, my buddies and I (along with most any other user) will be using it for D&D.
In D&D, modifiers are based on a character's stats. To get a modifier, you take the stat, subtract 10, divide by 2, and round down.
function getModifier(statValue) {
return Math.floor((statValue - 10) / 2);
}
My app will be capable to loading a game's rules from a .json file. I want to be able to make this modifier function user-definable. The easiest way would be to just eval() whatever they provide in the .json file, but obviously that's a terrible idea due to security issues.
Unfortunately, I can't think of a simple way to get around this in a secure manner. Obviously I could write my own parser, but that's more complicated than I'd like/am currently capable of.
Ideas?

I did a quick google search and found two options - http://mathjs.org and http://jsep.from.so
btw. writing your own parser is not that difficult. You may be able to write one that's sufficient for your purpose in less than 100 lines of code

First, bear in mind that this is all on the client-side. So long as you trust the JSON (it came from your server or it is controlled alongside the application itself), then you can use it. That doesn't completely rule out some trojan inserting malicious rules, but I don't think botnets have learned to play D&D yet.
To literally avoid eval and provide some modicum of security, you can use new Function. It takes a list of argument names followed by the function body, allowing you a large amount of control over how the function is defined and where it can be referenced from. You only need to store the body in the JSON file, allowing you to largely control the parameters and make it difficult to assign to the global scope, minimizing your attack surface (such as it is) quite a lot.
If you want to have fun with this and now your rules will largely be mathematical, you may consider using a tool like pegjs to generate a parser for your rules. Calculators are one of the classic introductions to parsers and compilers, so this could be an opportunity to play with some fun tech. The rules and parsers built by pegjs are very easy to use in a JS project (I have an example using PegJS and ES6 via Babel).

There are two options as I see it. One, if you 100% want to define the function in .json, you will need to parse. JSON does not allow functions, so you need to store the function as a string and eval it.
The better way would be to also provide a config.js ability. Perhaps the .json would have a "configUrl": property, and then expose well known apis, eg RPGHelper.setModifer(someFunction) that you can call from inside the config.js file. The user is then free to define whatever arbitrary logic there.

One solution to your problem is to use sandboxed iframes (current supported by all major browsers
You run user code on a separate page, with limited priviliges, in such a way that the code does not interfere with the rest of the application. You can communicate with the sandboxed page using postMessage() and window.onmessage.

Related

How can I sandbox code in an application with dynamically loaded, untrusted modules?

I'm making a game in Electron and I want it to support mods. Sometimes those mods will need to use custom logic, which leaves me with the issue of dynamically loading their code and I'm finding it hard to come up with a way to do that securely.
What I've considered
Ideally, I'd like to execute the mod scripts while passing just the few safe game objects they need as parameters, but that seems to be impossible (no matter the solution, that code can still access the global scope).
Most importantly, I have to prevent the untrusted code from accessing the preload global scope (with Node APIs), so require or anything else done in the preload is out the window.
Therefore that code has to be executed in the renderer.
My solution so far
I can either read the files in preload using fs or directly in the renderer using fetch. I have nodeIntegration set to false and contextIsolation set to true, and trusted code loaded by the preload script is selectively passed to the renderer through a contextBridge. The code which accesses Node APIs is properly encapsulated.
Unfortunately, that still leaves me with having to execute the unsafe code somehow, and I don't think there's any other way than to use eval or Function. Even though malicious code could not access Node APIs, it would still have full access to the renderer global scope, leaving the application vulnerable to, for example, a prototype pollution attack.
To sum up:
The safer place to execute untrusted code is clearly in the renderer
There is no alternative to using eval or Function
This leaves the renderer global scope vulnerable to attacks which I can try to mitigate but can never make it completely safe
My first question: are these assumptions true, or is there a better way to do it?
The risks and how to mitigate them
So the potentially malicious code has access to the renderer global scope. What's the risk?
Well, any sensitive user data will be safely stored in the preload, the same goes for access to the user's computer with Node APIs. The attacker can break the game (as in, the current 'session'), but I can catch any errors caused by that and reload the game with the malicious mod turned off. The global scope will only hold the necessary constructors and no actual instances of the game's classes. It seems somewhat safe, the worst thing that could happen is a reload of the game.
My second question: am I missing anything here regarding the risks?
My third question: are there any risks of using eval or Function that I'm not thinking of? I've sort of been bombarded with "eval bad" ever since I've started getting into JS and now I feel really dirty for even considering using it. To be exact, I'd probably be using new Function instead.
Thank you for reading this long thing!
There is no general solution for this, as this heavily depends on the structure of the project itself.
What you could try is to use espree to parse the unsafe code, and only execute it if there is no access to any global variable.
But that most likely will not prevent all attacks, because you might not think certain other attacks that might be possible due to the way the program is structured, require (or any other way to include/load other scripts) in that unsafe code could also open side channels allowing certain attacks.
eval and new Function are not bad in general, at least not as bad as loading/including unsafe code in any different way. Many libraries use code evaluation for generated code, and that's the purpose of those functions. But it is often misused in a situation in which there no need for that and that is something that should not be done.
The safest way is most likely to run the code in a WebWorker and define an API for the Mods to communicate between the mod and the application. But that requires to serialize and deserialize the data, when passing it form the app to the mod and the other way round, this can be expensive (but this is what is done e.g. with WebAssmebly). So I would read a bit how communication is solved with WebAssembly.

Name casing convention across all languages in an Application

I'm build a web app using Javascript (on the browser), C# and Sql Server. Is it a good idea to have a consistent naming convention across all three languages?
For Javscript, it seems to be best practice is to use camelCase, but in C# and Sql Server it's TitleCase.
Problem though is when the Javascript consumes and sends data to C# / Sql server the naming conventions are inconsistent. So I have to write code to map them.
For example
In Sql I have a table called 'Foo' with columns 'Name', 'EmailAddress'
In C# I have an POCO object called 'Foo' that maps to this table with
properties 'Name', 'EmailAddress' and exposes an api endpoint to GET this is
json
e.g {"Name": "Joe Bloggs", "EmailAddres":"joe#test.org"}
My Javascripts makes an ajax call to GET this JSON and maps it to its own
JSON object e.g {"name": data.Name, "emailAddress": data.EmailAddress}
This mapping between column/property naming conventions seems silly to me, and wouldn't be needed if all languages just agreed on casing convention. Is there a better approach to this?
In my opinion, you should continue to use the standard conventions for each language.
Benefits:
Consistency in each piece of software.
Easier for your fellow developer, since they won't need to learn a homebrew naming convention(s).
It will be easier to communicate code to the rest of the world in places like SO, or if you decide to to implement a solution found on SO.
Don't add extra conventions just to make the languages consistent. Your languages will end up with meaningless rules that are not relevant, and it'll be confusing to anyone who works on your code in the future.
To play Devil's Advocate, here's an opinion that disagrees with mine stolen from here:
This is where you find the big issue with coding standards based on
style - if your team doesn't write the entire codebase, then you're
going to find you have mismatches with the other code's standard.
So, my advice is not to sweat it. As long as your code is clear, it
really doesn't matter whether you use camel case, pascal case, or
underscore style. Its more important that the code is readable.
You should never alter the style of the 3rd parties as that will make
comparison with new versions impossible, so you have to stick with
them. If you have 2 different-style libraries, you have no choice but
to follow a standard that ignores code style. Its not that bad, if
you're a good coder you can read any code style. If you're not, having
a solitary style won't help you at all.
I include it because I think they make a good point, and because you're working on your own code outside of a team context. However, it's always good to practice good habits (or rather, avoid bad habits) on side projects, since they might carry through to code you write with/for others, so it would be beneficial to learn how to deal with naming conventions on a large codebase if you think you'll run into that issue in the future while on a team.
Add this to your application startup, and it should automatically convert the returned object of your GET to camelCase.
No need to futz with any mappings or stray from the conventions of each environment.
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
See here for more detail: http://odetocode.com/blogs/scott/archive/2013/03/25/asp-net-webapi-tip-3-camelcasing-json.aspx

Typesafety in javascript or how to avoid pretty hard to detect type related errors

I come from the Java world, i.e. a typesafe world and am right now doing a couple of things for which I need client side execution using javascript.
I keep running into pretty hard to detect errors at times due to the non typification of JS and am wondering if there is any way to prevent it beforehand. E.g. setting sth like "use typification;" or via some tool that does these checks before executing like a compiler does.
E.g. last time was when I was creating a face in three.js. There depening on order of vertices a face is front-facing or not. I had mixed that up and then copy pasted parameters in which case I also copied a bracket too much so it ended up in the wrong place with just calling the method with one instead of three vertices which of course resulted in an error. However in line 2107 of three.js code and it took a while to figure out this little copy paste issue. Comparing to java the compiler would have directly complained that i try calling the method with 1 instead of 3 parameters...
Hope there is sth like it. Or do have some tips how to spot such things faster?
Cheers
Tom
There are various linting tools which you can use to scan your javascript files before you actually use them. The popular ones in the industry are JSLint, JSHint, JSCS and ESLint.
They come inbuilt with various rule sets which you can configure and you can also add your own rules.
You can compare these to checkstyles and PMD from the JAVA world.
You have a number of answers. But first, need to clarify: Java is not type-safe (see: NullPointerException, history of).
But to get closer to type-safety in any dynamic language you have the option to pepper your code with asserts. This can to some degree be automated, it may cause performance issues. This is the route I usually take, but I certainly wouldn't do it with three.js.
For JavaScript specifically, you have two additional options: TypeScript and Flow.
TypeScript is a dialect of JavaScript with type annotations that gets compiled down to plain JS. Flow is a static analyzer written in OCaml that tries to infer types in your JS code and check them.

Closure Compiler: How to separate and control compilation/minification passes?

The Google Closure Compiler is a powerful compiler and minifier for JS, which gives a lot of optimization options such as renaming variables, removing dead codes, collapsing variable declarations, rewriting control flow structures and etc.
What I want is to separately apply one or some of these optimizations on an input JS program. For example, I may want to rename variables with short names, but not to remove dead codes. How can I achieve this kind of detailed compilation pass control? Does the source code of CC expose specific interfaces to do this customization, or I should write my own pass(If so, how am I supposed to start?).
The command line features do offer several options for controlling the compilation, but are insufficient to fit what I want above. Since the source code is kinda complicated and few detailed design documentation can be found, I am truly stuck here. Any insights would be appreciated, thanks :)
Take a look at DefaultPassConfig. That class lists all the passes that are run during the compilation, based on what options are set in the CompilerOptions. Some of the CompilerOptions can be controlled from the command line, but we generally try to keep the compiler relatively simple and easy to use, and not ask users to make decisions about a bunch of different compiler flags. Plus, there are some passes that actually increase the code size, but they do it in such a way that it makes it easier for some later pass to decrease it afterwards.
Of course if you're just experimenting with the compiler or trying to understand how it works, you can turn on and off whichever passes you want, either by adding new flags, or just modifying DefaultPassConfig directly.

Javascript bridge to Flash to store SO "cookies" within flash

After reading this on the question How do I uniquely identify computers visiting my web site?
:
A possibility is using flash cookies:
Ubiquitous availability (95 percent of visitors will probably have
flash)
You can store more data per cookie (up to 100 KB)
Shared across browsers, so more likely to uniquely identify a machine
Clearing the browser cookies does not remove the flash cookies.
You'll need to build a small (hidden)
flash movie to read and write them.
I tried to find if someone has already done something like this, so I wouldn´t have to reinvent the wheel. So far, no luck(maybe I don´t know the right term to search), except for the code in the flash side
The use I have for this is to prevent a user to answer a quiz multiple times, but future uses maybe banning trolls.
Does anyone knows a open source library that does this and allows me to access via javascript?
Caveats: I don't know flash and I don't own a license.
Edit: You can do that using evercookie. It's kind of evil, but works.
To build on what rmeador said, and to help get you started, you are going to need to know how to use two classes in the FLEX3 API, SharedObject and ExternalInterface.
SharedObject will allow you to store and retrive data from a client computer and ExternalInterface will allow your actionscript to communicate with your javascript.
Using shared object is simple.
To put data onto a users machine just create a SharedObject and add properities to the sharedObject's data properity.
private var sharedObject : SharedObject = SharedObject.getLocal("myCookie");
sharedObject.data.DATA_FOR_THE_COOKIE = DATA;
Retriving data from the SharedObject is just as simple. Make sure the size of the SharedObject is greater than 0 (Make sure the SharedObject exists) and the just look up the properity names through the SharedObject's data properity.
if(sharedObject.size > 0)
// access data from cookie with -> sharedObject.data.DATA_FROM_THE_COOKIE;
To pass the data stored in the SharedObject to your javascript you are going to need to use ExternalInterface.
Lets say you have a javascript function to retrieve the variables
function retrieveVars( vars ){
// Do something with vars.
}
To call this function from actionscript you will use
ExternalInterface.call("retrieveVars", DATA_ITEM_1, DATA_ITEM_2, ...);
Its that simple.
Please note that this technique will not work if the client's flash player has its storage settings set at 0, or if the client's browser does not have ActiveX or NPRuntime.
I'm hesitant to answer your question, because it sounds like this is straying dangerously close to Evil... Also, it's doomed to failure. If you really want to prevent a user from answering a quiz multiple times, the best thing you can do is have them register a user account. If you want to prevent them from registering multiple user accounts, you can have them verify something through a credit card or snail mail, both of which are generally untenable solutions. In short, the internet is anonymous.
Anyways, if you really want to go forward with this plan, you can build your application in Flex (a variant of Flash) fairly trivially. There's tons of documentation on the Adobe site. Some of it is rather sparse and annoying, particularly the collections API, but it'll be sufficient for your purposes. ActionScript (the programming language underlying both Flash and Flex) is very much like JavaScript and easy to learn. Flex has a free SDK (usually available in a small link from the page that tells you to get the expensive Flex Builder; Flex Builder is a primarily GUI tool, whereas you'll be writing straight code without an IDE with just the SDK), so a license shouldn't be a problem. The JavaScript to Flash bridge is also well documented.
BakedGoods seems to be exactly what you need (or rather, what you did need); its a Javascript library that establishes a uniform interface that can be used to conduct common storage operations in all native, and some non-native storage facilities, including Flash Locally Shared Objects (the "cookies" you speak of).
With it, creating an LSO can be accomplished with code as simple as:
bakedGoods.set({
data: [{key: "key", value: "value"}],
storageTypes: ["flash"],
complete: function(byStorageTypeRemovedItemKeysObj, byStorageTypeErrorObj){/*code*/}
});
Retrieving and removing data is just as easy. Trust me on all of this, I would know; i'm its maintainer :)
If for whatever reason you'd prefer to roll out your own solution, rmeador and ForYourOwnGood have supplied you with enough information to help you get started.
They've forgot to tell you how to do one very important thing, however: how to access, with Javascript, the Actionscript code that will handle the Shared Objects.
First, you will need to encapsulate your ActionScript code in a method, and then register that method as part of the ExternalInterface of its parent application:
function handleObjects(/*param1, param2, ... */):void {/*code*/}
ExternalInterface.addCallback("handleObjects");
Second, you will need to compile your Actionscript application (your code), and create an element in your HTML that references the resultant .swf file.
Then, assuming the aforementioned HTML element is represented as a DOMElement named flashDOMElement, you can call your method with the DOMElement:
flashDOMElement.handleSharedObjects(/*arg1, arg2, ... */);
And that's it! There are a couple of things that we've failed to mention or skimmed over, but all in all, rolling out your own solution is not hard. Rolling out your own reliable solution, however, is a different matter, which is partly why I suggest you use BakedGoods.
For people searching for this now, be sure do check out evercookie.
Evercookie definitely gets the job done, but this is a little closer to what you were originally asking for: https://github.com/nfriedly/Javascript-Flash-Cookies MIT license.

Categories

Resources