[jQuery] Securing AJAX/PHP against direct calls?
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
<blockquote cite="mid45C71D09.4070801@akbweb.de" type="cite">
<pre wrap="">Hi there,
do you have any ideas how I could secure my php files against direct
calls of the functions an ajax script calls? For example if I let my
AJAX script send a request to foo.php and foo.php returns a line of code
the AJAX script usually writes onto my site, how can I avoid that these
calls are submitted from outside/other sites can read these calls results.
</pre>
</blockquote>
Hi Arne-Kolja,
The best you can do is "Double submit the cookie", to ensure that the
user submits it not only from a browser that's validated, but also from
the same domain (or path even, if you set the cookie tight enough)
<a class="moz-txt-link-freetext"
href="http://www.ajaxian.com/archives/gmail-csrf-security-flaw">http://www.ajaxian.com/archives/gmail-csrf-security-flaw</a>
Siple hidden fields do _NOT_ protect you! It just makes the attack
slightly more convoluted, since the attacker will have to an extra
request to first get the hidden fields.
Checking the referer helps, but by doing that you'll also block a lot
of legitimate users.
What you should do is this:
1) When the user logs on to your app, set a cookie and a server
session, containing the same hash for that sessions:
$key = makeMySuperSecretHashKey();
<tt> $_SESSION['csrfcheck'] = $key;
setcookie(</tt><tt>'sessionhash', $key, time() +
$this->cookie_lifespan, $Paths['cookie_url'] );
</tt>
2) Whenever you're sending a form to the user, include a hidden
CSRFcheck field, that will be empty,
3) The browser uses a bit of JS to fill the field in the client,
before sending it to the server.
<pre id="line210"> <<span class="start-tag">input</span><span
class="attribute-name"> name</span>=<span class="attribute-value">'csrfcheck' </span><span
class="attribute-name">id</span>=<span class="attribute-value">'csrfcheck' </span><span
class="attribute-name">type</span>=<span class="attribute-value">'hidden' </span><span
class="attribute-name">value</span>=<span class="attribute-value">'' </span><span
class="attribute-name">/</span>>
<<span class="start-tag">script</span><span class="attribute-name"> type</span>=<span
class="attribute-value">'text/javascript'</span>>
$('#csrfcheck').val( $.cookie('sessionhash') );
</<span class="end-tag">script</span>>
</pre>
4) When the server receives the form, it checks if the local version of
the session hash is the same as the one that was sent with the form:
<blockquote><tt><?php </tt>
<tt> if ($_POST['csrfcheck'] != $_SESSION[ 'csrfcheck' ]) {</tt>
<tt> die('no cheating, please');
}
</tt><tt>?></tt>
</blockquote>
Alternatively, if you're doing AJAXy requests, without forms that are
being served first, you can still use a similar strategy:
<tt> var csrfcheck = $.cookie('sessionhash')
$.ajax({
type: "POST",
url: "ajaxhelper.php",
data: "csrfcheck=" + csrfcheck + "&contents=" + contents,
success: function(fetchedhtml) { alert(fetchedhtml); },
error: function() { alert("Error saving file.") }
}); </tt>
For this you'll need to use the Klaus' cookie plugin:
<a class="moz-txt-link-freetext"
href="http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/">http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/</a>
Hope this helps!
Best, Bob.
<pre wrap="">--
Bob den Otter - <a class="moz-txt-link-abbreviated"
href="mailto:bob@twokings.nl">bob@twokings.nl</a>
Two Kings - <a class="moz-txt-link-abbreviated"
href="http://www.twokings.nl">www.twokings.nl</a> - 070 345 76 28</pre>
</body>
</html>
_______________________________________________
jQuery mailing list
discuss@jquery.com
http://jquery.com/discuss/