JavaScript Function Constructor Parse Security - javascript

When using the Function constructor in JavaScript, a function object is dynamically created from the given code:
const input = 'return 2 + 3;'; // (1)
const fun = new Function(input); // (2)
const ret = fun(); // (3)
Assuming the input string (1) is arbitrary user input, is it insecure to parse it (2), even if it is never evaluated (3)?
EDIT:
I receive the string (1) directly from user input, e.g. via the web. It is completely unfiltered and I have no way to verify it beyond assuming it is malicious. I am ok putting a try/catch around the Function constructor to prevent syntax error on parse, but I am specifically interested in other security issues (mangling well-known globals, like in https://haacked.com/archive/2009/06/25/json-hijacking.aspx/).

It should be pretty safe. JSON hijacking is a bug that was fixed for exactly this reason.
Parsing it tells you only whether it is syntactically valid, there is no execution of any of the input. However, parsing can be costly in terms of performance, so if an attacker controls the input it might be able to be used to DOS your environment.

Related

Breakpoint on any string assignment if string contains a certain substring

Can I put a data breakpoint which triggers if any variable is assigned to a string containing a certain substring?
For example, I want to reverse-engineer how a URL containing &ctoken= is constructed. It's done with complicated JavaScript where the goal is to obfuscate it.
If I could tell the JS VM to monitor all string variables and break when a certain substring appears on any variable, this would help me a lot.
Is this possible?
Before I start - as of my knowledge this is not possible.
What you'd need (even before creating the debugging feature) is the raw string types already boxed to String the native built-in object and String then already proxied.
Some more explanation:
only having
const s = "hi"
is not yet an instance of String - the built-in native object, which is supplied by the ECMAScript implementation to your scope - but a raw type.
Such raw types are nothing more than pointers to a raw data memory reference. I even assume there are built in pools like in Java to optimize cases like
const s = "hi"
const x = new String("hi")
to be the same memory reference of the data object. but the later of course would be boxed by String.
http://bespin.cz/~ondras/html/classv8_1_1String.html
On raw types we couldn't - even if we wanted to - add a subscriber.
for example then:
s.charAt(i)
will autobox s to its wrapper String.
to observe every raw type would mean that we'd have to box all raw strings to String which wouldn't be a good thing for performance at all.
not only that but also the implementation of String itself would have to allow us to add a subscriber and therefore be proxied already.
in JS such proxy would look like this (to make it more understandable what I mean by proxied):
var proxiedString = new Proxy(String, {
defineProperty(target, propKey, propDesc) {
console.log('defined a new string')
},
set(obj, prop, value) {
console.log('set a new value to a string')
}
});
proxiedString.x = 'newPropValue'
and that again I guess - wouldn't be good for performance.
You can use condition breakpoints at browser devTools, by right
click with a menu.
If you can write a js somewhere in a page, you
can do this:
.
if(window.location.pathname.indexOf("&ctoken=") > -1){
debugger;// browser will put breakpoint automaticaly here, if condition is trully.
console.dir(window.location);
}

Securing JavaScript eval function

We want to give our users the ability to execute self created JavaScript code within our application. For this we need to use eval to evaluate the code. To reduce all security concerns to a minimum (if not zero), our idea is to prevent the usage of any window or document function within the code. So no XMLHttpRequest or anything similar.
This is the code:
function secure_eval(s) {
var ret;
(function(){
var copyXMLHttpRequest = XMLHttpRequest; // save orginal function in copy
XMLHttpRequest = undefined; // make orignal function unavailable
(function() {
var copyXMLHttpRequest; // prevent access to copy
try {
ret = eval(s)
} catch(e) {
console.log("syntax error or illegal function used");
}
}())
XMLHttpRequest = copyXMLHttpRequest; // restore original function
}())
return ret;
}
This works as follows:
secure_eval('new XMLHttpRequest()'); // ==> "illegal function used"
Now I have several questions:
Is this pattern the right way to secure eval?
What functions of window and document are the ones which are considered harmful?
To ship around question 2. I tried to mask all (native) functions of window But I am not able to enumerate them:
This does not list XMLHttpRequest for instance:
for( var x in window) {
if( window[x] instanceof Function) {
console.log(x);
}
}
Is there a way to get a list of all native functions of window and document?
EDIT:
One of my ideas is to perform the eval within a Worker and prevent access to XMLHttpRequest and document.createElement (see my solution above). This would have (to my mind) the following consequences:
no access to the original document
no access to the original window
no chance to communicate with external resources (no ajax, no scripts)
Do you see any drawback or leaks here?
EDIT2:
In the meantime I have found this question which answer solves many of my problems plus a couple of things I did not even think about (i.e. browser dead lock with "while(true){}".
Your code does not actually prevent the use of XMLHttpRequest. I can instantiate an XMLHttpRequest object with these methods:
secure_eval("secure_eval = eval"); // Yep, this completely overwrites secure_eval.
secure_eval("XMLHttpRequest()");
Or:
secure_eval("new (window.open().XMLHttpRequest)()")
Or:
secure_eval("new (document.getElementById('frame').contentWindow.XMLHttpRequest)()")
This 3rd method relies on the presence of an iframe in the HTML of the page, which someone could add by manipulating the DOM in their browser. I do such manipulations every now and then with Greasemonkey to remove annoyances or fix broken GUIs.
This took me about 5 minutes to figure out, and I am not by any means a security guru. And these are only the holes I was able to find quickly, there are probably others, that I don't know about. The lesson here is that it is really really really hard to secure code through eval.
Using A Worker
Ok, so using a Worker to run the code is going to take care of the 2nd and 3rd cases above because there's no window accessible in a Worker. And... hmm.. the 1st case can be handled by shadowing secure_eval inside its scope. End of story? If only...
If I put secure_eval inside a web worker and run the following code, I can reacquire XMLHttpRequest:
secure_eval("var old_log = console.log; console.log = function () { foo = XMLHttpRequest; old_log.apply(this, arguments); };");
console.log("blah");
console.log(secure_eval("foo"));
The principle is to override a function that is used outside secure_eval to capture XMLHttpRequest by assigning it to a variable that will be deliberately leaked to the global space of the worker, wait until that function is used by the worker outside secure_eval, and then grab the saved value. The first console.log above simulates the use of the tampered function outside secure_eval and the 2nd console.log shows that the value was captured. I've used console.log because why not? But really any function in the global space could be modified like this.
Actually, why wait until the worker may use some function we tampered with? Here's another, better, quicker way to do access XMLHttpRequest:
secure_eval("setTimeout(function () { console.log(XMLHttpRequest);}, 0);");
Even in a worker (with a pristine console.log), this will output the actual value of XMLHttpRequest to the console. I'll also note that the value of this inside the function passed to setTimeout is the global scope object (i.e. window when not in a worker, or self in a worker), unaffected by any variable shadowing.
What About the Other Question Mentioned in This Question?
What about the solution here? Much much better but there is still a hole when run in Chrome 38:
makeWorkerExecuteSomeCode('event.target.XMLHttpRequest',
function (answer) { console.log( answer ); });
This will show:
function XMLHttpRequest() { [native code] }
Again, I'm no security guru or cracker bent on causing trouble. There are probably still more ways I'm not thinking about.
I'll try and answer your questions in order here.
Is this pattern the right way to secure eval?
This part is slightly subjective. I don't see any major security drawbacks to this. I tried several ways to access XMLHttpRequest, but i couldn't:
secure_eval('XMLHttpRequest')
secure_eval('window.XMLHttpRequest')
secure_eval('eval("XMLHttpRequest")()')
secure_eval('window.__proto__.XMLHttpRequest') // nope, it's not inherited
However, it will be a lot if you want to blacklist more things.
What functions of window and document are the ones which are considered harmful?
That depends on what you consider "harmful". Is it bad if the DOM is accessible at all? Or what about WebKit desktop notifications, or speech synthesis?
You'll have to decide this based on your specific use case.
To ship around question 2. I tried to mask all (native) functions of window, but I am not able to enumerate them:
That's because most of the methods are non-enumerable. To enumerate, you can use Object.getOwnPropertyNames(window):
var globals = Object.getOwnPropertyNames(window);
for (var i = 0; i < globals.length; i++) {
if( window[globals[i]] instanceof Function) {
console.log(globals[i]);
}
}
One of my ideas is to perform the eval within a Worker and prevent access to XMLHttpRequest and document.createElement (see my solution above).
This sounds like a good idea.
I stumbled across a really, really nice blog article about the notorious Eval here. The article does discuss in detail. You won't be able to alleviate all security concerns, but you can prevent Cross-Script Attacks by building tokens for the input. This would in theory prevent malicious code that could be harmful from being introduced.
Your only other hurdle will be Man-In-The-Middle Attacks. I'm not sure if that would be possible, as you can't trust input and output.
The Mozilla Developer Network does explicitly state:
eval() is a dangerous function, which executes the code it's passed
with the privileges of the caller. If you run eval() with a string
that could be affected by a malicious party, you may end up running
malicious code on the user's machine with the permissions of your
webpage / extension. More importantly, third party code can see the
scope in which eval() was invoked, which can lead to possible attacks
in ways to which the similar Function is not susceptible.
eval() is also generally slower than the alternatives, since it has to
invoke the JS interpreter, while many other constructs are optimized
by modern JS engines.
There are safer (and faster!) alternatives to eval() for common
use-cases.
I'm slightly against Eval and truly try to use it when warranted.
I have stated it yet in my question, but to make it more clear I will post it as an answer also:
I think the accepted answer on this question is the correct and only way to completely isolate and constrain eval().
It is also secure against these hacks:
(new ('hello'.constructor.constructor)('alert("hello from global");'))()
(function(){return this;})().alert("hello again from global!");
while(true){} // if no worker --> R.I.P. browser tab
Array(5000000000).join("adasdadadasd") // memory --> boom!
There was a question long ago much like this. So I dusted off some old code and fixed it up.
It essentially works by taking advantage of the with keyword and providing it with a frozen empty object. The prototype of the empty object is filled with null properties, the keys of which match the names global variables like self, window and their enumerable property keys; The prototype object is also frozen. eval is then called within the with statement (Almost the same way that scripts run with an implicit with(window){} block if I understand correctly). When you try to access window or its properties you get redirected (via the with block) to null versions (with same key) found in empty object (or rather the empty object's prototype):
function buildQuarantinedEval(){
var empty=(function(){
var exceptionKeys = [
"eval", "Object", //need exceptions for these else error. (ie, 'Exception: redefining eval is deprecated')
"Number", "String", "Boolean", "RegExp", "JSON", "Date", "Array", "Math",
"this",
"strEval"
];
var forbiddenKeys=["window","self"];
var forbidden=Object.create(null);
[window,this,self].forEach(function(obj){
Object.getOwnPropertyNames(obj).forEach(function(key){
forbidden[key]=null;
});
//just making sure we get everything
Object.keys(obj).forEach(function(key){
forbidden[key]=null;
});
for(var key in obj){
forbidden[key]=null;
}
});
forbiddenKeys.forEach(function(key){
forbidden[key]=null;
});
exceptionKeys.forEach(function(key){
delete forbidden[key];
});
Object.freeze(forbidden);
var empty=Object.create(forbidden);
Object.freeze(empty);
return empty;
})();
return function(strEval){
return (function(empty,strEval){
try{
with(empty){
return eval(strEval);
}
}
catch(err){
return err.message;
}
}).call(empty,empty,strEval);
};
}
Setup by building a function/closure that evaluates some expression:
var qeval=buildQuarantinedEval();
qeval("'some expression'"); //evaluate
Tests:
var testBattery=[
"'abc'","8*8","console","window","location","XMLHttpRequest",
"console","eval('1+1+1')","eval('7/9+1')","Date.now()","document",
"/^http:/","JSON.stringify({a:0,b:1,c:2})","HTMLElement","typeof(window)",
"Object.keys(window)","Object.getOwnPropertyNames(window)",
"var result; try{result=window.location.href;}catch(err){result=err.message;}; result;",
"parseInt('z')","Math.random()",
"[1,2,3,4,8].reduce(function(p,c){return p+c;},0);"
];
var qeval=buildQuarantinedEval();
testBattery.map(function(code){
const pad=" ";
var result= qeval(code);
if(typeof(result)=="undefined")result= "undefined";
if(result===null)result= "null";
return (code+pad).slice(0,16)+": \t"+result;
}).join("\n");
Results:
/*
'abc' : abc
8*8 : 64
console : null
window : null
location : null
XMLHttpRequest : null
console : null
eval('1+1+1') : 3
eval('7/9+1') : 1.7777777777777777
Date.now() : 1415335338588
document : null
/^http:/ : /^http:/
JSON.stringify({: {"a":0,"b":1,"c":2}
HTMLElement : null
typeof(window) : object
Object.keys(wind: window is not an object
Object.getOwnPro: can't convert null to object
var result; try{: window is null
parseInt('z') : parseInt is not a function
Math.random() : 0.8405481658901747
[1,2,3,4,8].redu: 18
*/
Notes: This technique can fail when some properties of window are defined late (after initializing/creating our quarantined eval function). In the past, I've noticed some property keys are not enumerated until after you access the property, after which Object.keys or Object.getOwnPropertyNames will finally be able grab their keys. On the other hand this technique can also be quite aggressive in blocking objects/functions you do not want blocked (an example would be like parseInt); In these cases, you'll need to manually add global objects/functions that you do want into the exceptionKeys array.
*edit* Additional considerations: How well this all performs depends entirely on how well the mask matches that of the property keys of the window object. Any time you add an element to the document and give it a new ID, you just inserted a new property into the global window object, potentially allowing our 'attacker' to grab it and break out of the quarantine/firewall we've setup (i.e. access element.querySelector then eventually window obj from there). So the mask (i.e., the variable forbidden) either needs to be updated constantly perhap with watch method or rebuilt each time; The former conflicts with the necessity of the mask to have a frozen interface, and the latter is kinda expensive having to enumerate all the keys of window for each evaluation.
Like I said earlier, this is mostly old code I was working on, then abandoned, that was quickly fixed up on short order. So it's not by any means thoroughly tested. I'll leave that to you.
and a jsfiddle
I have small idea about secure eval for small or limited things if you know well what u going to use eval in you can create white list and black list and excute only the strings that has the valid but it good for small covered app for example calculator has few options (x, y) and (+,*,-,/) if i added this characters in white list and add check for script length and study what excepted length of the script run it can be secure and no one can pass that
const x = 5;
const y = 10;
function secureEval(hack_string){
// 0 risk eval calculator
const whiteList = ['',' ', 'x', 'y','+','*','/','-'];
for (let i=0; i<hack_string.length; i++){
if (!whiteList.includes(hack_string[i])){
return 'Sorry u can not hack my systems';
}
}
return 'good code system identify result is : ' + eval(hack_string);
}
// bad code
document.getElementById("secure_demo").innerHTML = secureEval('x * y; alert("hacked")');
document.getElementById("demo").innerHTML = secureEval('x * y');
<!DOCTYPE html>
<html>
<body>
<h1>Secure Eval</h1>
<p id="secure_demo"></p>
<p id="demo"></p>
</body>
</html>

How do I convert a string into an executable line of code in Javascript?

I have the following bit of code
console.log("I am");
var x = "console.log('Alive!')";
Now I only want to use x to execute the code-string that is assigned to it - I may not even know the value of x for example but simply want to execute it whatever it maybe - is this possible?
eval() This will convert string to javascript code.
eval("console.log('Alive! Woo!')");
eval and new Function let you parse and execute JavaScript code from strings.
In general, avoid executing code from strings. And never execute code from strings where the strings are untrusted input (for instance, if you take input from user A, never use these to evaluate it in a session with user B).
I see answers here pointing you at eval. eval grants access to your local variables and such to the code, making it really powerful and really dangerous if you use it with untrusted input.
Where possible, avoid eval. You can easily avoid it in your case:
For instance:
console.log("I am");
var x = "console.log('Alive!')";
new Function(x)();
That code creates a function whose body is the text from x, then immediately executes the function.
What you are looking for is eval(). By passing a string to this function you will evaluate the string as JavaScript code and it will return whatever return-value the code in the string returns.
Be aware when using this function though. You do not want to evaluate any code you do not know is safe to execute. For example, running user-generated code could mess up whatever you are making. While using this in JavaScript on a website this will probably only cause issues on the client-side and hence probably won't be much of a security threat, you would want to be VERY careful when evaluating code on for example a server side.
As have been hinted to in other posts here you probably want to make a function instead of an evaluated string if you are in control of the source code that is to be run.
What you are looking for is called a function:
function x() {
console.log('Alive!');
}
If x is already a string containing the code you could use eval(x) to execute it. eval is evil though.
var x = "console.log('Alive!')";
eval(x)

Javascript security question / Using eval()

I'm seeing code in the following form - is such use of eval() safe?
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset=eval("document."+frm_name);
var x=eval("document."+frm_name+".edit_key");
var y=eval("document."+frm_name+".cAction")
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
Its used as:
<a href="javaScript:;" onClick="genericTakeAction('frmSearch',
'<?php echo $rec_id;?>','<?php echo $pagenum?>','makeOpen')"
class='link6'>Make Open</a>
Whether it's right or wrong, it's needlessly complicated.
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset = document[frm_name];
var x = rset.edit_key;
var y = rset.cAction;
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
This works because in JavaScript, you can access an object's properties in one of two ways: Either using dotted syntax and a literal identifier, e.g. x = obj.foo;, or using bracket syntax and a string identifier, e.g. x = obj["foo"];. (Note how foo was not in quotes in the first one, but was in quotes for the second; but both do exactly the same thing. Also note that since the property name is a string in the second case, you can use any expression that results in a string, so y = "f"; x = obj[y + "oo"]; also works.)
P.S. It's wrong
eval() is generally frowned upon because, as you are already aware, it is considered unsafe.
In the browser environment, however, it is less of an issue, because in fact, any user could eval() any code they wanted to, using tools like Firebug, etc.
There is still an issue, in that the eval() embedded in the code can be run without the user knowing that he was triggering an eval(), but it's still much less of an issue than in a server-side environment like PHP.
eval() is actually typically used as you've shown to run JSON code being returned from a server-side request. Newer browsers can import JSON more safely using a dedicated JSON parse() function, but older browsers do not have this function and are forced to use eval() for this. Most JSON libraries have eval() in their code somewhere for this reason, but will generally do some sanitisation of the input before running it through eval().
Even if it might look a little bit convoluted, as others have already mentioned, from a pure security perspective, you have to make sure that the 'frm_name' parameter of the genericTakeAction() function can never contain user-supplied data.
In your example, the 'frm_name' parameter contains the hard-coded literal 'frmSearch'. So it is ok as long as this genericTakeAction() function does not get called somewhere else with user-supplied data for the 'frm_name' parameter.
See http://en.wikipedia.org/wiki/Cross-site_scripting#Traditional_versus_DOM-based_vulnerabilities

Is there a way to jail in Javascript, so that the DOM isn't visible

I would really like to provide the user some scripting capabilities, while not giving it access to the more powerful features, like altering the DOM. That is, all input/output is tunneled thru a given interface. Like a kind of restricted javacsript.
Example:
If the interface is checkanswer(func)
this are allowed:
checkanswer( function (x,y)={
return x+y;
}
but these are not allowed:
alert(1)
document.write("hello world")
eval("alert()")
EDIT: what I had in mind was a simple language that was implemented using javascript, something like http://stevehanov.ca/blog/index.php?id=92
(Edit This answer relates to your pre-edit question. Don't know of any script languages implemented using Javascript, although I expect there are some. For instance, at one point someone wrote BASIC for Javascript (used to have a link, but it rotted). The remainder of this answer is therefore pretty academic, but I've left it just for discussion, illustration, and even cautionary purposes. Also, I definitely agree with bobince's points — don't do this yourself, use the work of others, such as Caja.)
If you allow any scripting in user-generated content, be ready for the fact you'll be entering an arms race of people finding holes in your protection mechanisms and exploiting them, and you responding to those exploits. I think I'd probably shy away from it, but you know your community and your options for dealing with abuse. So if you're prepared for that:
Because of the way that Javascript does symbol resolution, it seems like it should be possible to evaluate a script in a context where window, document, ActiveXObject, XMLHttpRequest, and similar don't have their usual meanings:
// Define the scoper
var Scoper = (function() {
var rv = {};
rv.scope = function(codeString) {
var window,
document,
ActiveXObject,
XMLHttpRequest,
alert,
setTimeout,
setInterval,
clearTimeout,
clearInterval,
Function,
arguments;
// etc., etc., etc.
// Just declaring `arguments` doesn't work (which makes
// sense, actually), but overwriting it does
arguments = undefined;
// Execute the code; still probably pretty unsafe!
eval(codeString);
};
return rv;;
})();
// Usage:
Scoper.scope(codeString);
(Now that uses the evil eval, but I can't immediately think of a way to shadow the default objects cross-browser without using eval, and if you're receiving the code as text anyway...)
But it doesn't work, it's only a partial solution (more below). The logic there is that any attempt within the code in codeString to access window (for instance) will access the local variable window, not the global; and the same for the others. Unfortunately, because of the way symbols are resolved, any property of window can be accessed with or without the window. prefix (alert, for instance), so you have to list those too. This could be a long list, not least because as bobince points out, IE dumps any DOM element with a name or an ID onto window. So you'd probably have to put all of this in its own iframe so you can do an end-run around that problem and "only" have to deal with the standard stuff. Also note how I made the scope function a property of an object, and then you only call it through the property. That's so that this is set to the Scoper instance (otherwise, on a raw function call, this defaults to window!).
But, as bobince points out, there are just so many different ways to get at things. For instance, this code in codeString successfully breaks the jail above:
(new ('hello'.constructor.constructor)('alert("hello from global");'))()
Now, maybe you could update the jail to make that specific exploit not work (mucking about with the constructor properties on all — all — of the built-in objects), but I tend to doubt it. And if you could, someone (like Bob) would just come up with a new exploit, like this one:
(function(){return this;})().alert("hello again from global!");
Hence the "arms race."
The only really thorough way to do this would be to have a proper Javascript parser built into your site, parse their code and check for illegal accesses, and only then let the code run. It's a lot of work, but if your use-case justifies it...
T.J. Crowder makes an excellent point about the "arms race." It's going to be very tough to build a watertight sandbox.
it's possible to override certain functions, though, quite easily.
Simple functions:
JavaScript: Overriding alert()
And according to this question, even overriding things like document.write is as simple as
document.write = function(str) {}
if that works in the browsers you need to support (I assume it works in all of them), that may be the best solution.
Alternative options:
Sandboxing the script into an IFrame on a different subdomain. It would be possible to manipulate its own DOM and emit alert()s and such, but the surrounding site would remain untouched. You may have to do this anyway, no matter which method(s) you choose
Parsing the user's code using a white list of allowed functions. Awfully complex to do as well, because there are so many notations and variations to take care of.
There are several methods to monitor the DOM for changes, and I'm pretty sure it's possible to build a mechanism that reverts any changes immediately, quite similar to Windows's DLL management. But it's going to be awfully complex to build and very resource-intensive.
Not really. JavaScript is an extremely dynamic language with many hidden or browser-specific features that can be used to break out of any kind of jail you can devise.
Don't try to take this on yourself. Consider using an existing ‘mini-JS-like-language’ project such as Caja.
Sounds like you need to process the user entered data and replace invalid mark-up based on a white list or black-list of allowed content.
You can do it the same way as Facebook did. They're preprocessing all the javascript sources, adding a prefix to all the names other than their own wrapper APIs'.
I got another way: use google gears WorkerPool api
See this
http://code.google.com/apis/gears/api_workerpool.html
A created worker does not have access
to the DOM; objects like document and
window exist only on the main page.
This is a consequence of workers not
sharing any execution state. However,
workers do have access to all
JavaScript built-in functions. Most
Gears methods can also be used,
through a global variable that is
automatically defined:
google.gears.factory. (One exception
is the LocalServer file submitter,
which requires the DOM.) For other
functionality, created workers can ask
the main page to carry out requests.
What about this pattern in order to implement a sandbox?
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
That returns:
Number
undefined
undefined
MathConstructor
JSON
undefined
undefined
-0.9999987317275395
3.14
Can you please provide an exploit suitable to attack this solution ? Just to understand and improve my knowledge, of course :)
THANKS!
This is now easily possible with sandboxed IFrames:
var codeFunction = function(x, y) {
alert("Malicious code!");
return x + y;
}
var iframe = document.createElement("iframe");
iframe.sandbox = "allow-scripts";
iframe.style.display = "none";
iframe.src = `data:text/html,
<script>
var customFunction = ${codeFunction.toString()};
window.onmessage = function(e) {
parent.postMessage(customFunction(e.data.x, e.data.y), '*'); // Get arguments from input object
}
</script>`;
document.body.appendChild(iframe);
iframe.onload = function() {
iframe.contentWindow.postMessage({ // Input object
x: 5,
y: 6
}, "*");
}
window.onmessage = function(e) {
console.log(e.data); // 11
document.body.removeChild(iframe);
}

Categories