In the previous post, we covered how easy it is to build an environment where anyone can write in HTML, CSS, JS code that gets rendered and displayed in a sandbox (iframe) in realtime. It’s all good as long as the platform is restricted to yourself, but when it becomes open, i.e., when others can create testcases or use it for some other purpose as on CSSDeck, you need to start thinking about security.
What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.
Problems
Let me first cover some of the problems with our current approach where we simply manipulate the contents of the iframe
.
Access To The Parent Window
The main (or top or parent or whatever you want to call it) window object is accessible from inside the iframe:
window.top // or window.parent // maybe some more ways!
That piece of code is enough to access the parent window, using which one can do anything on it. For example injecting scripts, audios, videos, manipulating the DOM in any way, redirecting to another site via the location
object, etc.
Now, if Mr. Hacker creates an item with some nasty Javascript code that does one or more of the aforementioned actions, it could hurt anyone who tries to access it. Danger for users!
Same Origin Attacks
Mr. Hacker writes a piece of code that makes an API call to a URL on the same origin to possibly fetch Username, User Email, User ID, etc. and then submits some random form (again on the same origin) with those details. Lots of spam for you and your users. Oh! and he has your user’s precious email now.
If you don’t know what same and different origins mean, then read this article on MDN.
Solution
The solution is to have the iframe on a different origin. For example, <iframe src="http://subdomain.yoursite.com"></iframe>
. But now, how do we achieve realtime rendering with the iframe
being on a different origin ?
HTML5 postMessage to the Rescue
HTML5 comes with a new API – postMessage that is well supported by all major browsers. Even IE8 and up supports it, but only for frames and iframes, NOT other tabs or windows. We are dealing with iframes anyway.
This allows us to safely communicate with an iframe on a different origin. I am not going to explain it in details as MDN does a very good job at that.
Now all you have to do is, send the source (JSON.stringify
it if required) to the iframe
using iframe_node.contentWindow.postMessage()
. In the iframe you receive the data, check origin (for security) and perform the same operations we covered in the previous post, which is: 1. Using document.open
, document.write
and document.close
or 2. Creating and Injecting style and script nodes (with a body node for HTML if required or set the innerHTML property of the document.body
).
Notes
Hey, I want to tell you something. You should be a good ethical person! If you ever find security issues on any site related to anything, you should try NOT to harm them, but instead inform them about the vulnerabilities. This way you can not only help them out, but also help the community they have built around. Maybe the patches they develop to fix the issues will get released back into the community, which means more and more people are going to benefit and we’re going to have access to better softwares and services.
Isn’t that awesome ? You earn more karmas!
Coming Up
Wouldn’t it be nice if we had a really nice text editor over plain textarea
elements that supported syntax highlighting, indentation and lots of other cool stuffs to enhance our coding experience. Exactly what we’ll cover in the next part.