Thursday, April 5th, 2007
Protecting a JavaScript Service
<p>There is increasing buzz over security with JavaScript, and people are stepping up to the plate.In How to Protect a JSON or Javascript Service, Joe Walker looks at a few solutions such as:
- Use a Secret in the Request
- Force pre-eval() Processing
- Force POST requests
Joe implements some of these in DWR, including:
Prefix the script with throw new Error("message");. This is a neat solution in that it allows you to explain what is wrong to users that get the message by mistake.
Andrea Giammarchi wonders if 130 bytes are enough to solve JavaScript JSON Hijacking problems? in which he discusses tactics for detecting the hijacking of your objects and comes up with solutions such as this:
-
-
if((function(c,m,t){t=c[m];delete c[m];if(/^[XMLHttpRequest]$/.test(c)){c[m]=t;return 1}})(XMLHttpRequest,"toString"))
-
alert("Valid XMLHttpRequest");
-
else
-
alert("XMLHttpRequest is corrupted");
-
Finally, the GWT team has published an article on Security for GWT Applications that delves into how GWT handles JavaScript vulnerabilities such as leaking data, cross-site scripting, forging requests, JSON and XSRF.
A lot of good stuff.
Related Content:











KISS:
$headers = getallheaders();if(isset($headers['X-Requested-With']) &&
$headers['X-Requested-With'] == 'XmlHttpRequest') {
//...
}
Nathar, are You sure that a redefined XMLHttpRequest object cannot use setRequestHeader with that property?
Andrea, that doesn’t matter. Any attempt to use XMLHttpRequest (or any redefined variation thereof) is restricted by the same-origin policy which means it cannot access data from another domain. i.e., a site at http://www.angelfire.com/~hacker/ cannot access data from http://www.googlemail.com. If it uses a script tag, it cannot set any HTTP headers and so googlemail.com can block it. If it uses XMLHttpRequest, it can call setRequestHeader, but the request would be automatically denied by the browser because it is going to a different domain. Thus, Google can ensure that their JSON data is only accessible to sites hosted on http://www.googlemail.com.
What about just passing:
(function(){return {..json..};))
That’s simple, the json cannot be accessed without calling the lambda. Seems like the easy answer…
One gotcha to keep in mind is that if your server supports the Range header, someone could just use a byte range to fetch the inside of your JSON, rendering your comments and error throwing useless.