Recently I started looking at my AJAX call security and found some code that uses tokens, request and referer in an attempt to authenticate the call and stop XSS and CSRF.
The AJAX calls are for the article list / article table in the admin section.
Note: The PHP will not run unless you are logged in — it uses a cookie and sessions to authenticate user.
EDIT: Implemented schisms function name suggestion.
The following code works as it should but is it a good method?
Create our Token:
$token = md5(rand(1000,9999)); $_SESSION['token'] = $token;
The button to deactivate / activate an article:
<td> if($article_active === 1){ echo '<input type="button" class="active_button" title="Deactivate" value="YES" name="'.$article_id.'"/>'; } else { echo '<input type="button" class="active_button" title="Activate" value="NO" name="'.$article_id.'" />'; } echo ' </td>
The AJAX call:
// ACTIVATE / DEACTIVATE WITH LINK $(document).on("click",".active_button",function() { var form_data = { articleID: $(this).attr("name"), active: $(this).val(), selector: $("#selector").attr("name"), data: $("#data").val(), token:'<?php echo $token; ?>', is_ajax: 1 }; $.ajax({ type: "POST", url: "controllers/articlecontrol.php", data: form_data, success: function(data){ document.location.reload(true); } }); });
The PHP that validates the AJAX request and sends the data to a PHP function:
// ACTIVATE / DEACTIVATE w/BUTTON if(isset($_POST['active']) && $selector === 'article') { if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' && isset($_POST['token']) && $_POST['token'] === $_SESSION['token']){ $articleid = $_POST['articleID']; $active = ($_POST['active'] === 'YES') ? 0 : 1; $backend->setArticleStatus($articleid, $active); } else { $_SESSION['status'] = '<div class="error">There was a Problem Activating / Deactivating that Article</div>'; } }
The PHP activate / deactivate function (part of a class):
/** * Activate / Deactivate Article w/Button */ public function setArticleStatus($articleid, $active) { $query = 'UPDATE wcx_articles SET article_active = :active WHERE article_id = :articleid'; $stmt = $this->queryIt($query); $stmt = $this->bind(':active', $active); $stmt = $this->bind(':articleid', $articleid); if($this->execute()) { if ($active === 0) { $_SESSION['status'] = '<div class="success">Article Deactivated Successfully</div>'; } else { $_SESSION['status'] = '<div class="success">Article Activated Successfully</div>'; } } else { $_SESSION['status'] = '<div class="error">There was a Problem Activating / Deactivating that Article</div>'; } }
XSS
attacks it seems that$token
stops them just fine. I am using$bits = 32; $token = bin2hex(openssl_random_pseudo_bytes($bits));
for the token now, so its truly random.\$\endgroup\$