Pure Javascript Sandbox - javascript

Is this a possible solution for a pure javascript sandbox ?
My willing is to execute an untrusted string of code without giving access to DOM, window, this, and so on but allowing the user to acces Math, JSON and other functionalities.
I've tested it on Chrome.
UPDATE:
I want to give the possibility to save on server user-defined code and make it available to other users. I'm looking for a way to deny access to the document ni order to make it safe.
function safe(code,args)
{
if (!args)
args=[];
return (function(){
for (i in window)
eval("var "+i+";");
return function(){return eval(code);}.apply(0,args);
})();
}
ff=function()
{
return 3.14;
}
console.log(safe("this;"));//Number
console.log(safe("window;"));//undefined
console.log(safe("console;"));//undefined
console.log(safe("Math;"));//MathConstructor
console.log(safe("JSON;"));//JSON
console.log(safe("Element;"));//undefined
console.log(safe("document;"));//undefined
console.log(safe("Math.cos(arguments[0]);",[3.14]));//-0.9999987317275395
console.log(safe("arguments[0]();",[ff]));//3.14
I've proposed it on an old post : https://stackoverflow.com/a/11513690/76081
Thanks!

It's unsafe. The following construction will get the global window object from inside your sandbox:
(function(){return this;})()
At which point, you can extract anything you want from it, including goodies like document.
Hat tip to T.J. Crowder for his answer on https://stackoverflow.com/a/2673780/149341 in which he described this exploit.

Related

Javascript. How to use original JSON object (that was redefined by another developer) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have a simple JS code like:
JSON.stringify({'a':'b'});
that works ok when is run standalone on my webpage. But when my code is put inside the production environment, some extra javascript files ruin my code totally. One of those extra js files has JSON object redefinition. And now my code is using this version of JSON object I don't want to use.
How can I tell javascript to use a built-in JSON object, not a custom one?
Some clarification:
This JSON object redefinition is done inside core javascript production libraries (my code is inserted inside old CMS). It looks like core developer wanted to create his own polyfill for old browsers. I am afraid to change his code.
Thank you in advance!
You can use the old trick with an iframe to restore the global object:
// some other code breaks global JSON
window.JSON = {
stringify() { return "it's broken"; },
parse() { return "it's broken"; }
}
const obj = {foo: 1};
console.log(JSON.stringify(obj)); // it's broken
//later your code runs
(function() {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const origJSON = iframe.contentWindow.JSON;
document.body.removeChild(iframe);
const json = origJSON.stringify(obj);
console.log(json); // '{"foo":1}'
console.log(origJSON.parse(json)); // { foo: 1 }
//restore the global JSON
window.JSON = origJSON;
})();
//afterwards global JSON works
const json = JSON.stringify(obj);
console.log(json); // '{"foo":1}'
console.log(JSON.parse(json)); // { foo: 1 }
However, this is not a reliable way to deal with these issue. It should only serve as a temporary workaround. In general, if your environment is broken due to some script outside of your control, you cannot guarantee the environment works correctly as long as the script is there.
Here is a simple example: let us say that script A.js breaks the global JSON object. Your script is C.js where you do restore JSON with your code. However, B.js runs after A.js and before C.js and tries to use JSON. It gets a wrong value and continues to use it. However, will not function correctly. Your environment is now still broken even after you fixed it.
It is an exceptionally bad idea to tamper with global objects. If any script does that, you are better off trying to replace it or fix it than continue to use it.
By far, your best bet is to not include the file that redefines JSON, because JSON is defined in a particular way by the specification and shouldn't be overridden by something doing something different. Lots of things may well break (not just your code).
If you can't do that, you have a couple of choices:
Make sure your script is first and create a local variable private to your script and assign JSON to it, then use that local. You can even make the local JSON, like this:
;((JSON) => {
// ...your code here...
))(JSON);
If your script has to be after the other one, then put a new script before it that saves the original JSON:
const originalJSON = JSON;
Then, again, use that in your code, perhaps like this:
;((JSON) => {
// ...your code here...
))(originalJSON);

restore overridden window.JSON object

Some code that I don't have control over is overriding the global JSON object without checking if it's already implemented:
var JSON = {
org: "http://www.JSON.org",
copyright: "(c)2005 JSON.org",
license: "http://www.crockford.com/JSON/license.html",
stringify: function(a, g) {
...
The problem is that this version of the JSON parser is very old and has a bug, which is fouling up my attempts at serialization. (Others have had a similar problem with this implementation.)
Can I get at the browser's native implementation? I thought delete would work, but it doesn't. I suspect that's because JSON is an object and not a method in the prototype. Is there some other way to get at it?
You can create an iframe element (which will load about:blank and hence create a new context) and get a JSON object from there.
function restoreJSON() {
var f = document.createElement("iframe");
f.style.display = "none";
document.documentElement.appendChild(f);
window.JSON = f.contentWindow.JSON;
document.documentElement.removeChild(f);
}
about:blank is loaded synchronously, so no need to wait for the load event. While this isn't restoring the original JSON object, it is getting one black-box identical to it.
Since the code that you don't have control over is overriding the original before you come along in the page, you have two options:
Inject an iframe and grab the JSON off the contextWindow (as indicated in the other answer on this question at the time of this edit), or, alternately, just use the https://github.com/douglascrockford/JSON-js JSON library as your own insert. Note that using Crockford's does give cross-browser-guarantees of conformance, but the native implementations are often faster.
An alternative if you have the ability in the future to come along on the page before the offending code, is to inject something before that offending "code that helps" to grab the JSON object:
<html>
<head>
<script>
window.myJson = window.JSON;
</script>
....

referencing the html object that made the ExternalInterface.call to the javascript function called

i apologize if my terminology is off, my actionscript skills are pretty weak sauce.
so, i have some actionscript that makes a
ExternalInterface.call('someFunction');
call.
is it possible to reference the html object that made the call to someFunction directly using the ExternalInterface.call call?
Assume that the object that makes the call also has some Callbacks (via ExternalInterface.addCallback) that are accessible via javascript.
Currently:
Actionscript source
ExternalInterface.call("someFunction");
ExternalInterface.addCallback("someCallback",someASfunction);
Javascript source
function someFunction(){
document.getElementById('idOfSWFObject').someCallback();
}
I'm thinking there must be a way of:
Actionscript source
ExternalInterface.call("someFunction",THE_OBJECT_MAKING_THE_CALL);
ExternalInterface.addCallback("someCallback",someASfunction);
Javascript source
function someFunction(o){
o.someCallback();
}
once again, sorry about the terminology. tried to lace it with as many keywords for future searches.
thanks!
I guess you are talking about ExternalInterface.objectID. This property returns an id associated with flash container in object or embed tag.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html?filter_flex=4.1&filter_flashplayer=10.2&filter_air=2.en#objectID
I suggest that you should also pass the name of "someCallback" to you JS method. This way there will be no need to hardcode it in JS.
Here's an example
// Actionscript source
const jsMethodName:String = "someFunction";
const asCallbackName:String = "someCallback";
ExternalInterface.call(jsMethodName+"(document.getElementById("++")"++");");
ExternalInterface.addCallback(asCallbackName,someASfunction);
// Javascript source
function someFunction(flashId, callbackName)
{
var flashContainer = document.getElementById(flashId);
flashContainer["callbackName"]();
}
EDIT: If you really want to get a reference to flash DOM object in someFunction arguments, you may achieve it in a bit tricky way (I would rather not, but just for your interest).
// Actionscript source
const jsMethodName:String = "someFunction";
const asCallbackName:String = "someCallback";
ExternalInterface.addCallback(asCallbackName,someASfunction);
ExternalInterface.call(
"function(){"+
jsMethodName+"("+
"document.getElementById('"+ExternalInterface.objectID+"'),"+
"'"+asCallbackName+"'"+
");"+
"}"
);
// Javascript source
function someFunction(flashContainer, callbackName)
{
flashContainer[callbackName]();
}
This way you inject some JS code from flash into js. It works, but looks messy.

How to parse JSON created by WCF DataContract object

I have an object decorated with [DataContract] attribute and my WCF service is returning this as JSON like this:
{"GetCommentsByPostResult":[{"CommentCreated":"\/Date(1305736030505+0100)\/","CommentText":"Comment 1"},{"CommentCreated":"\/Date(1305736030505+0100)\/","CommentText":"Comment 2"},{"CommentCreated":"\/Date(1305736030505+0100)\/","CommentText":"Comment 2"}]});
Ive attempted to iterate through the CommentCreated with this jQuery code:
$(data).each(function ()
{
alert(this.CommentCreated);
});
But all I get is an alert box with 'undefined in' so I changed it to:
$(data).each(function () {
$(this.GetCommentsByPostResult).each(function () {
alert(this.GetCommentsByPostResult);
});
});
but that still doesnt work. What I want to do is iterate the CommentCreated and throw them to an alert box....
I'm not sure, but I don't think this would be the current element when calling each. Also, why are you wrapping the data variable with the jQuery function? jQuery collections are for DOM elements.
$.each(data.GetCommentsByPostResult, function (e) {
alert(e.CommentCreated);
});
Depending on how you are acquiring the data (a library? custom code?) you will most likely have to convert the JSON string first into an actual JavaScript object. Many browsers have built in methods for doing this, though you may need to take advantage of a 3rd party library to take advantage of those that do not have out-of-box support. I would recommend JSON-js as it follows the same syntax as those found built into some browsers.
var obj = JSON.parse(data);
Once you have this object, you can now access the data with standard JavaScript dot or bracket notation:
var comments = obj.GetCommentsByPostResult; // or...
var comments = obj['GetCommentsByPostResult'];
Those two lines are equivalent. To iterate the comments, as you are trying to do, you could try:
$.each(obj.GetCommentsByPostResult, function (e) {
alert(e.CommentCreated);
});
Also, I would recommend using console.log() instead of alert(), and a browser that supports inspection of the logged objects. This would be FireFox with the Firebug extension, or Chrome with their developer tools (Ctrl-Shift-J to activate). Not sure about the status of this type of tool in IE9, though I would not be surprised if there was an equivalent tool there as well.

Get ExternalInterface definitions in Javascript

Is there a way to get a list of the exposed functions from a Flash object? For example, you could get a list of all methods in an object by executing:
for (var i in object) {
if (typeof object[i] == "function") {
console.log(i);
}
}
The only issue is that this won't expose any methods registered through the ExternalInterfaces API. I can try and see if the function exists (object['method']) and it tells me it is a function, but I would have to guess every existing method in this manner.
NOTE: Obviously, I don't have access to the actionscript.
Just hit this question, a tad to late it seems, but I'll post an answer anyways ;)
Using IE10 (windows 7) it worked perfectly fine for me to list all my methods like so:
var obj = document.getElementById('flashObj');
for(var prop in obj){
var fx = obj[prop];
if(obj.hasOwnProperty(prop) && (typeof fx == 'function') && /eval\(instance/.test(fx)){
console.log(prop)
}
}
Note that this did not work in Chrome or Firefox and only with the exact regexp since IE10 does not report "native code" as the other browsers do.
The problem is even worse: the information is neither available in ActionScript. You register a new function as ExternalInterface.addCallback('foo', foo) and you can not list already registered callbacks.
Just a guess but see if it works. All the ExternalInterface functions should be defined in the global namespace. Try embedding the SWF in an HTML page and get all the Javascript functions defined for the page after the page has loaded. List of global user defined functions in JavaScript?
The list of functions should be those defined in the SWF file.
I guess the only way to go is to parse the SWF file bytecode and try to gather the calls to ExternalInterface.addCallback method.
http://www.google.com/search?q=parse+avm2
My instinct is no, ExternalInterface is essentially a black box, or black letter box, you poke things through and sometimes things come back, but you can't open the door to see what's inside.
Without documentation as to what's been exposed in the SWF, the only other suggestion is decompiling the swf to have a look at the source.

Categories