Javascript, the minefield
When a few of us from the LimeSpot team began using LimeSpot for our own blogs, we quickly realized that content scrubbing is a real pain. We had been whitelisting tags, which meant that any time we discovered we needed a new tag we'd have to add it to the LimeSpot codebase. Furthermore, there are some tags that we can't add because malicious users can do bad things with them.
User-generated javascript is one of those things that presents so many opportunities but is so dangerous that most sites remove it completely. One of the main dangers of user-generated javascript is cookie theft—malicious users can embed javascript that steals other users' cookies and thus gain access to the users' accounts. Another danger is the possibility of user-generated javascript executing an AJAX post request to do something malicious such as deleting the user's own account.
Because of these vulnerabilities, users usually have to have their own hosting in order to use Javascript. For LimeSpot we wanted something a bit more.
Our first approach was to try and protect the cookies. Several browsers now have support for HTTP-only cookies, but there are still too many browsers that do not. Also, javascript allows too many methods for evaluating code for us to simply remove the methods for retrieving cookies. What we ended up doing was moving all user-generated content into separate subdomains, leaving limespot.com for administrative tasks. By putting users' sites on separate domains, javascript that is executed there cannot access the cookies on limespot.com. We split our cookies into trusted cookies and untrusted cookies. Trusted cookies are set for limespot.com and allow users to do anything they please, whereas untrusted cookies are set for (your site).limespot.com and only allow a few actions, such as leaving comments for that particular site.
Each untrusted site cookie needs to be linked with a trusted limespot cookie, so we used <script> tags register the untrusted cookie: (it conveniently renders our lime bar as well)
<script src="http://limespot.com/sessions/lime_bar?app_id=3
&app_session_id=123456789abcde&site_id=1" type="text/javascript"></script>
When we receive this on limespot.com, we go ahead and set up an app_session that is linked with the user's real (trusted) session. This way we can always tell who a user is, but we know to limit their privileges when they are on user-generated sites.
There are still a few kinks to be worked out, but we think this is a pretty good way to mix trusted and untrusted markup in the same web application.
Comments
sup