I am planning to create an open source education web app where people can add and edit the content (a bit like Wikipedia).
However I wish to add another feature that allows the user to add their own interactive content using JavaScript. (similar how JSFiddle does it)
What are the security concerns in doing this?
Optional question: How can these issues be overcome?
Yes you could use HTML5 Sandbox to only load user scripts in an IFrame.
You should only host user content from a different domain than your main site. This will prevent any XSS attack if an attacker convinces a user to visit the page directly (outside of the sandbox). e.g. if your site is www.example.com
you could use the following code to display the sandboxed IFrame:
<iframe src="https://www.foo.com/show_user_script.aspx?id=123" sandbox="allow-scripts"></iframe>
This will allow scripts, but forms and navigation outside of the IFrame will be prevented.
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
You should test whether sandbox is supported first, before rendering the IFrame:
<iframe src="/blank.htm" sandbox="allow-scripts" id="foo"></iframe>
var sandboxSupported = "sandbox" in document.createElement("iframe");
if (sandboxSupported) {
document.getElementById('foo').setAttribute('src', 'https://www.foo.com/show_user_script.aspx?id=123');
}
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.
As @Snowburnt touches upon, there is nothing stopping a user script from redirecting a user to a site where a drive-by download occurs, but this approach, assuming a user is up to date on patches, and there are no zero day vulnerabilities, this is a safe approach because it protects its end users and their data on your site via the same origin policy.
One big issue is cross-site scripting where users add code that tells the browser to open and run code from other sites. Say they add something that creates an iFrame or a hidden iFrame pointing to a site and starts downloading malicious code.
There's no simple way around it (thanks to Bergi in the comments) to make sure no elements are created and no ajax calls are made.
I've been a member of sites that provided this functionality, but for those sites I paid for my own space so any vulnerabilities I add are inconveniencing my own clients, in that case it's a little more okay to let that slip by since it's not a security leak for everyone.
One way around this is to create customizable controls for the users to use to add interactivity. The plus is that you control the javascript being added, the minus is that your user base will have to request and then wait for you to create them.