<br><br><div class="gmail_quote">On Sun, Mar 28, 2010 at 7:12 AM, Jon mailinglists <span dir="ltr"><<a href="mailto:jon.mlist@gmail.com">jon.mlist@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
In my catalyst app I have this sub (not really, but this makes things<br>
easier to follow):<br>
<br>
sub get_info : Local {<br>
my ($self, $c) = @_;<br>
<br>
my $info = $c->user->member_info;<br>
my $res = 'MyNamespace.callback({"ResultSet":{"totalResultsAvailable":"73399","firstResultPosition":"0","totalResultsReturned":"20","Result":[{"Title":"'.$info->get_column('first_name').'<br>
'.$info->get_column('last_name').'","zip_code":"'.$info->get_column('areacode').'"}]}});';<br>
$c->response->body($res);<br>
}<br></blockquote><div><br></div><div>I think I get it now. I first thought you were talking about users adding javascript to pages you render -- that is, allowing someone to inject script onto your pages.</div><div><br>
</div><div>(I'm hoping someone will jump in an correct anything I say wrong here -- which often seems like the best way to get a response here...) </div><div><br></div><div>I think the short answer is, don't return JSONP -- don't return JSON wrapped in a function call. That's a way to bypass security provided by the same-origin policy.</div>
<div><br></div><div>Let me restate what I think you are saying:</div><div><br></div><div><ol><li>The "good site" (MY-CATALYST-SERVER in your example) returns the JSONP above as long as the user is logged in. By "logged in" that means the request includes a valid session id in the cookie.</li>
<li>In another tab of the same browser when viewing a page from "<a href="http://evil_empire.com">evil_empire.com</a>" a request is made to <a href="http://MY-CATALYST-SERVER:3000/member/get_info">http://MY-CATALYST-SERVER:3000/member/get_info</a>.</li>
<li>That request will include the cookie required to gain access (and thus return private user data).</li><li>Javascript is returned that includes a call to a function passing the user's private data to that function.</li>
<li><a href="http://evil_empire.com">evil_empire.com</a> now has access to the user's name and zip code.</li></ol><div>Yes, this is true. This is a security hole. But by returning JSONP you gave away this access.</div>
</div><div><br></div><div>JSONP is "application/javascript" -- and as such it can be loaded from any domain. Loading javascript is not limited by same-origin policy. (If it was then Content Delivery Networks would be of limited use.).</div>
<div><br></div><div>Note, this has nothing to do with YUI.Get. <a href="http://evil_empire.com">evil_empire.com</a> just needs to add a <script> tag to their page to fetch the JSONP from your app. YUI.Get just provides a dynamic way to accomplish that.</div>
<div><br></div><div>Your application should only return data via JSON, not JSONP. For a script to read JSON data it needs to use XMLHttpRequest and that request is limited by the same-origin policy. That is, javascript running on <a href="http://evil_empire.com">evil_empire.com</a>'s page cannot do an AJAX request to your catalyst application.</div>
<div><br></div><div>Hopefully, that's clear -- and correct. ;)</div><div><br></div></div><br>-- <br>Bill Moseley<br><a href="mailto:moseley@hank.org">moseley@hank.org</a><br>