views:

69

answers:

5

I'm working on creating one of those robot games. The user creates a robot and then puts it in a battlefield with other robots.

I'd like to let the users use javascript to program their bots. I'll provide a number of functions for them to call, but they also can build thier own. (sorta)

To date, the only solution I have come up with is to use the javascript eval() function to execute the code the users have written.

I want to know two things:

  1. Anyone have any alternative suggested implementations that still allow the users to write in javascript?

  2. Can the users do anything with this flaw that they could not do using the firefox javascript debugging tools? (ie: on their own without my use of the eval() function)

Note: The javascript code is stored within mySQL. ajax is used to pull the jscript out and display to users. ajax is used to send javascript updates back into SQL. All code submitted by users and about to be inserted in the database is run through a "clean()" function.

A: 

Many AJAX libraries can be set to execute the returned JS automatically. No need for eval().

Diodeus
It's a game, so each "bot" in the game executes one line, I then increment and the next round starts...so it's not like a full set of scripts that make up each bot.
Markus
That's fine. Regardless of the size of the returned JS, you can still execute it without eval().
Diodeus
Erm, which AJAX libraries manage to execute the returned JS without eval?
unomi
+3  A: 

So basically you will allow UserA to write javascript which will be evalled in UserB's browser?

If so, then that sounds like a fairly bad idea ;)

You could use a middle layer such as http://code.google.com/p/google-caja/wiki/CajaCajole to make it a bit safer.

An example of what they could do is: write javascript which will present what looks like your login page, then send the username and password to another server.

Another example would be to inject a script tag which then gets the 'full' payload which could get up to all kinds of mischief, like fx showing a friendly popup with the new exclusive downloadable Portal game that you got a special deal with Steam to make available etc etc. Just download and Run! Then it creates a hidden iframe to some trojan cdn. :)

unomi
Good point about script injection. If it's for anything more than a small 'trusted' audience you'd definitely want a pretty serious firewall between user A's javascript and user B's browser. I was assuming that's what the `clean()` function in the OP was trying to do...
no
He could also simply dismantle UserB's robot through Javascript — `robotB.leftArm = null`, etc.
Chuck
That was so dastardly even I didn't think of it.
unomi
@Chuck: Yes, that's the sort of thing I had in mind when I suggested `Function`... if the main game logic is scoped inside an anonymous function, `new Function("robotB.die()")()` would throw a ReferenceError, which I assume would be caught by the game and cause robotA to die ;)
no
A: 

The most important thing is to let pages containing user scripts run on a separate, "sandboxed" domain that has no session cookies from the main site that could be connected to user accounts and such.

That, together with some manual monitoring of the submissions, will already take away a lot of the script injection risks.

There will always be some risk of malicious code being run on the user's browser when allowing Javascript from your users, but it stands to reason that getting malicious JavaScript is a general risk on the Internet, and it's up to the client to protect against it.

What I wouldn't do is eval() user-entered JavaScript inside the main domain of the project. That opens too many real dangers of attack.

Pekka
+2  A: 

I never thought I'll say this, but Project Narcissus might be of use to you. It's a JavaScript engine written in JavaScript.

Reality Analyst
I'll have to check this out.
Markus
+2  A: 

Cool idea.

eval does have a slight disadvantage against other methods of script injection.

You can create a function on the fly with Function. Try this:

var command = "alert(123)";
var doStuff = new Function(command);
doStuff();

eval runs in the private scope, Function runs in the global scope. That means if you have an internal value that bots aren't supposed to be able to modify, they might have access to it if you run their logic through eval, but they shouldn't if you use Function. More info here:

http://stackoverflow.com/questions/3338397/changing-string-to-a-function-in-javascript-not-eval/3338533#3338533

no
I see your point, but part of the game is that the bots WILL alter other variables in the environment(app). This is ok, but needs to be done through a select number of functions.
Markus
@Markus: You could pass the environment data into the function like this: `new Function("gameData", command)(gameData)`
no