suppose I work with some kind of API and my file server.php handles the connection to the API service. on my client side I use AJAX call like this:
$http({
url : 'server/server.php',
method : 'GET',
data : { getContent : true }
});
in my server.php I handle it like this:
if(isset($_GET['getContent'])){
$content = get_content();
}
function get_content(){...}
i just wonder what prevents any one send AJAX call with the same getContent parameter and get all my data? how can i secure it and make sure only calls from my application will get the relevant data back?
thank you!
I guess you are concerned about CSRF attacks. Read more about this here: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet
One of the mostly used option to secure your request will be: - Generate a token and send it with the request for a session. This token can be identified by your WebServer as originating from a specific client for a specific session
This is a 7 year old post and the link in the link-only "accepted" answer is broken.
So, I'm going to offer a basic walkthrough and a complete model.
Remember, the $_SESSION
will be preserved even in the AJAX handler, if it's all from the same domain. So, you can use that to check things.
$_POST
I presume you're using $_POST
and not $_GET
since you're concerned about security. If not, then much of this might not be important anyway.
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$post_method = true;
}
$_SERVER['HTTP_REFERER']
is from your own siteif ( (!empty($_SERVER['HTTP_REFERER']))
&& ($_SERVER['HTTP_REFERER'] === "https://example.tld/my_sending_page.php") ) {
$from_my_server = true;
}
If you're not sure what this should be, run a test on your own server to see what this should be:
echo $_SERVER['HTTP_REFERER'];
$_SERVER
arrayif ( (!empty($_SERVER['HTTP_X_REQUESTED_WITH']))
&& ( strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') ) {
$ajax = true;
} else {
$ajax = false;
}
This is the hard part, but not too hard.
$_SESSION
$_SESSION
tokensend_from_me.php
// Create the token
//$token = md5(rand(10000,99999)); // Not recommended, but possible
$token = bin2hex(random_bytes(64));
// Store in SESSION
$_SESSION["token"] = $token;
// Assuming your AJAX is this
const AJAX = new XMLHttpRequest();
// This goes inside your AJAX function somewhere before AJAX.send
//
AJAX.setRequestHeader("ajax-token", "<?php echo $_SESSION["token"]; ?>");
//
// That creates $_SERVER['HTTP_AJAX_TOKEN'] which we can use later
ajax_responder.php
session_start(); // Must have
if ($_SERVER['HTTP_AJAX_TOKEN'] === $_SESSION["token"]) {
$token_match = true;
} else {
echo "No script kiddies!";
exit();
}
// Now it's safe for your AJAX responder to proceed
sending_from.php
<?php
session_start();
$token = bin2hex(random_bytes(64));
$_SESSION["token"] = $token;
?>
<!DOCTYPE html>
<html>
<head>
<title>My AJAX Sender</title>
</head>
<body>
<script>
function ajaxFormData(formID, postTo, ajaxUpdate) {
// Bind a new event listener every time the <form> is changed:
const FORM = document.getElementById(formID); // <form> by ID
const FD = new FormData(FORM); // Bind to-send data to form element
const AJAX = new XMLHttpRequest(); // AJAX handler
// This runs when AJAX responds
AJAX.addEventListener( "load", function(event) {
document.getElementById(ajaxUpdate).innerHTML = event.target.responseText;
} );
// This runs if AJAX fails
AJAX.addEventListener( "error", function(event) {
document.getElementById(ajaxUpdate).innerHTML = 'Oops! Something went wrong.';
} );
// Add your token header
AJAX.setRequestHeader("ajax-token", "<?php echo $_SESSION["token"]; ?>");
// Open the POST connection
AJAX.open("POST", postTo);
// Data sent is from the form
AJAX.send(FD);
}
</script>
<div id="ajax_changes">Replace me with AJAX</div>
<form id="ajaxForm">
<input type="text" name="the_simple_response">
<button type="button" onclick="ajaxFormData('ajaxForm', 'ajax_responder.php', 'ajax_changes');">Send my Secure AJAX</button>
</form>
</body>
</html>
ajaxcheck.inc.php
<?php
$mysite = 'https://example.tld';
// All in one test
if (($_SERVER['REQUEST_METHOD'] == 'POST')
&& ((!empty($_SERVER['HTTP_REFERER'])) && ($_SERVER['HTTP_REFERER'] === "$mysite/my_sending_page.php"))
&& ((!empty($_SERVER['HTTP_X_REQUESTED_WITH'])) && ( strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'))
&& ($_SERVER['HTTP_AJAX_TOKEN'] === $_SESSION["token"])) {
$ajax_legit = true;
} else {
echo "No script kiddies!";
exit();
}
?>
ajax_responder.php
<?php
session_start();
// Do all that checking we're learning about by neatly including the file above
require_once('ajaxcheck.inc.php');
// Process your AJAX
echo $_POST['the_simple_response'];
?>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With