Javascript security question / Using eval() - javascript

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

Related

Javascript alternative of eval()

the eval() does exactly what i want, but when i look at doc in MDN,it says
Do not ever use eval!
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, a 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 slower than the alternatives, since it has to invoke the JS interpreter, while many other constructs are optimized by modern JS engines.
Additionally, modern javascript interpreters convert javascript to machine code. This means that any concept of variable naming gets obliterated. Thus, any use of eval will force the browser to do long expensive variable name lookups to figure out where the variable exists in the machine code and set it's value. Additonally, new things can be introduced to that variable through eval() such as changing the type of that variable, forcing the browser to reevaluate all of the generated machine code to compensate. However, there (thankfully) exists a very good alternative to eval: simply using window.Function. As an example of how you convert code using evil eval() to using Function().
what is the better option for me. my code is like:
let aCount=0;
let bCount=0;
addCount=(option)=>{ //option either a or b
const choice=eval(option+"Count"); // then combine to aCount or bCount
choice++;
}
addCount(a);//aCount=1;
addCount(a);//aCount=2;
addCount(b);//bCount=1;
addCount(b);//bCount=2;
i try window[variable] before, but it doesn't return value
i can't do thing like
const choice=window[option+"Count"]
it will return undefined.
and i need to call choice many times so it's not gonna work for me to repeat window[variable].
Besides "eval", there has some error in you example code, and I'm not going to explain for you.
And now we focus on "eval" in your example. If you do so, you'll find it won't work at all. You can only do this like eval(option + "Count++"), rather than assign the value of aCount/bCount to a (CONST!) variable, and then increase that variable. The following code has logical problem:
let c = aCount;
c++; // aCount not changed
In my opinion, you can use "eval" in some special situation, as long as the code passed into "eval" is ABSOLUTELY trusted. In your example code, it corresponds this rule. (However, besides security, "eval" also has performance issue.)
Of course, you have other better choices to avoid using "eval". For example, use if/else or switch/case:
addCount=(option)=>{
if (option === 'a') aCount++;
else if (option === 'b') bCount++;
}
Or, you can use an object to hold all variables:
let obj = {aCount: 0, bCount: 0};
addCount=(option)=>{
obj[option + "Count"]++;
}

How to parse a string into javascript object?

I have a javascript object defined inside a string variable:
const str = "{a:1}";
I wonder what is the best way to convert it to a javascript object. I have searched a lot but all I found is to use JSON.parse or JSON.stringify to convert the string. But the tricky part in this string is that it is not a JSON object. The a is not quoted. I have tried below approach but it doesn't parse it to a object:
JSON.parse(JSON.stringify(str))
I know I can parse the string manually but I am looking for a more generic solution which support parsing all possible javascript object string.
var obj = eval(str);
Just be aware that using eval can have performance and security impacts.
If you don't control the content of str, i.e. it is a user input or it comes from a server you don't trust, the are risks.
Also, the JavaScript runtimes optimizes your code at runtime, but often disable many optimizations when engineering an eval.
Try to wrap the evaluation statement in a self invoked function that receive the variable passed to theeval:
(function(s) {
return eval(s);
}(str));
It ensures the creation of a closure to isolate the eval, mitigating it's potential impacts.
And last, don't take anything I've just said as an absolute truth: benchmark your code with and without the eval, just to be sure.

Eval() function alternative

I have a json file where i am rendering the template and have an object like
"templateLabelEval":"return $row->['document_code'];"
I am rendering the label by using
eval(templateLabelEval);
Is there any other alternative way where i could avoid using eval as it is considered to be a bad practice
Given that the code string has a return statement, eval alone wouldn't work anyway, but you could use Function().
var result = Function(data.templateLabelEval)();
This has nearly all the same security concerns, but not so much the performance issues that eval has (or had). So of course, you should only execute code that is secure.
To explain the code, passing the string to the Function constructor creates a new function object with that strings as its body. (I assume the function needs no parameters defined for now.) So the trailing () invokes the function immediately and the result is stored in result.
You could store the function itself if you want, and then invoke it later as many times as you'd like.

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)

Evaluate the string as object (javascript)

Here is the problem string:
$.ajax(......
,success:function(msg){
var obj = eval('['+msg.d+']');
},
....
}
msg.d contains something like:
new Person(2, 'Name Surname','This is just string came from Par'is at Sat'urday');
How can pass the javascript problem ?
If the string really is as you've quoted it, it has a syntax error and will not work (it has an errant ' inside the word "Saturday"). Otherwise, though, change the brackets ([ and ]) in your eval call to parentheses (( and )):
var obj = eval('('+msg.d+')');
However, it should almost never actually be necessary to do this (or indeed to use eval at all). It's almost always possible, and desirable, to refactor slightly and avoid it.
If that's a literal quote from your code, see also dvhh's answer below, your function argument name (msg.d) is invalid.
Using eval in this scenario is actual quite dangerous. You really ought to be using XML or JSON. (That's why they call it AJAX.)
the function argument should be a valid javascript identifier
try changing msg.d to msg_d for example
You may need to escape your string, because this example works fine:
function MyObject(myvar){
this.hello = function(){
alert('myvar= ' + myvar);
};
}
var obj1 = new MyObject('hello');
obj1.hello();
var obj2 = eval("new MyObject('world')");
obj2.hello();
(Edit: By the way, I assume msg.d is a typo due to editing the snipplet before posting on StackOverflow ?)
I would avoid using eval() for security reasons. If a user can get malicious code into the database, there's a chance it could end up in this eval expression, wreaking havoc for anybody who visits this page.
Instead of using eval, I'd recommending returning JSON from the AJAX request. You can then easily parse the values and build a new Person object with that data.

Categories