Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

javascript - Is my eval() safe?

I built a dice roller here: http://howderek.com/projects/diediedie/

and I wanted to implement math so that my users could preform mathmatical operations to their rolls, which is useful for RPGs.

Instead of building a function to handle the math, or using a library like math.js, I figured that since JavaScript has math built in, this might be a good use for eval().

The reason I am concerned with the eval() however, is that appending ?q=whatever to the url of DieDieDie enters whatever into the box and passed it to DieDieDie

Now, obviously, if this was purely just an eval console, it would be easy to abuse and run malicious JavaScript through, but it's not, I use a RegEx before running eval()

From (http://howderek.com/projects/diediedie/js/diediedie.js):

if (!replaced.match(/[^0-9 | + | - | * | / | ( | ) | . | % | > | <]/g)) {
    result = eval(replaced);
} else {
    throw 'Unsafe eval (more than just math), refusing to execute.';
}

So, I was wondering if there was any way to circumvent the RegEx, and run code though that eval() just by entering text into the box.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Complexity is the enemy of security, so I find it best to implement a simple solution that you know is secure rather than attempting to come up with something more complicated that has possibly made something safe (but no one is quite sure until an exploit is found).

A safe way to do it is that you could use a HTML5 Sandbox to load a page hosting your script, then you do not need to be concerned about whether your RegEx can be bypassed.

You will need to host the page under a different domain than your main site (e.g. script.example.com instead of www.example.com). This will prevent any XSS attack if an attacker convinces a user to visit the page directly (outside of the sandbox).

You will need to enable scripts within the IFrame by using code like this:

<iframe src="http://script.example.com/projects/diediedie/" sandbox="allow-scripts" />

This will allow scripts, but in the case of an exploit being found to your RegEx, forms and navigation outside of the IFrame will be prevented. As it is on a different domain, your main site cannot be attacked via XSS.

The HTML5 Security Cheat Sheet guidance on OWASP states this is the purpose of the sandbox:

Use the sandbox attribute of an iframe for untrusted content

As you are allowing untrusted content to run via eval (albeit "sanitised" via RegEx), this seems like an appropriate use of the sandboxed IFrame.

You should test whether sandbox is supported first, before rendering the IFrame:

<iframe src="/blank.htm" sandbox="allow-scripts" id="foo" />

var sandboxSupported = "sandbox" in document.createElement("iframe");

if (sandboxSupported) {
    document.getElementById('foo').setAttribute('src', 'http://script.example.com/projects/diediedie/');
}
else
{
    // Not safe to display IFrame
}

It is safer to do it this way by dynamically changing the src rather than redirecting away if sandboxSupported is false because then the iframe will not accidentally be rendered if the redirect doesn't happen in time.

To enable this to work cross-domain (between script.example.com and www.example.com) you will need to use HTML5's Window.postMessage functionality. This will enable secure communication between the IFrame and the outer window. Note that setting document.domain is not secure as it will defeat the purpose of hosting the page on a separate domain in the first place.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...