-1

How could I be sure that my php has been invoked by my javascript posted on my web page only and from an authenticated user only? I would like to prevent attacks or data-stealing from other web sites or other unauthorized users who e.g. could invoke my php script and get/delete some of my data without the permission. As I know $_SERVER['HTTP_REFERER'] could be easily changed so it's not reliable so I can't be sure that my php has been invoked from my javascript on my web page. The Cookies are not reliable too, so I can't be sure that the userID that I stored in the cookies as an authorized user who properly logged in, hasn't been craked and changed. So how to make a javascript/php web app safe? Any suggestion? Thank you.

Leonardo
  • 751
  • 8
  • 15
  • 1
    You can generate random string in php save it in session and in a cookie after authentication then you check in php if value from cookie is the same as in session. – jcubic May 30 '16 at 10:38
  • You can't make sure the form was sent via javascript. but you can authenticate with sessions. Not sure that @jcubic understood the question.. – Viktor Koncsek May 30 '16 at 10:44
  • @jcubic, as I wrote and know, the cookies are not reliable. They can be read by others. – Leonardo May 30 '16 at 10:52
  • Instead of cookie you can add custom header. First you echo random string in javascript from php and then you append custom header to each ajax request and check that header in php. And if you don't use ajax you can add hidden field to forms. – jcubic May 30 '16 at 10:55

1 Answers1

1

Take a look at How do I provide more security for checking source of the request.

It sounds like you are afraid of Cross-Site Request Forgery (CSRF) on your site. Follow the link to learn more about CSRF.

As a rule of thumb you always do your security backend. Below is an example of a secret handshake method you can use.

This method guarantees that the user has at least started his series of request by knowing the first secret:

Generate a unique value for the user in PHP and make it a hash of something unique to the user that you can easily recreate:

$secretHandshake = hash('sha512', $user_id . '_' . $secret_counter);

Put this somewhere on your site where JavaScript can get it. A hidden input field is good for this.

Now when you AJAX, simply submit the secret with the AJAX as a parameter:

var secret = jQuery("#secret").val();
jQuery.ajax({
  url: "doStuff.php",
  method: "POST",
  data: {action: 'createUser', data: /* whatever */, secret: secret}
}).success(function(response) {
  //Save the new secret
  response = JSON.parse(response);
  secret = response.secret;
});

Now we can simply validate the request on the server:

if(!isset($_POST['secret']) || /* User not logged in check */) {
    die();
}
if($_POST['secret'] === $secretHandshake) {
    //Now that we have validated the respone, we create a new secret
    $secret_counter++;
    $secretHandshake = hash('sha512', $user_id . '_' . $secret_counter);
    $returner = array('secret' => $secretHandshake);

    //Do something with the data

    //Append extra responses if relevant:
    $returner['data'] = 'Success!';

    //Return as json for JavaScript
    echo json_encode($returner);
}

This makes it harder for bots to attack your site since the must know the current secret for each request.

Community
  • 1
  • 1
Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
  • Thanks Emil. That can work for bots. Anyway a human could always read the secret string and invoke the php script from a browser passing other parameters. I think there should be a way to make everything secret. – Leonardo May 30 '16 at 11:19
  • @Leonardo The problem with frontend security is that the user can always peek at how it works and thus better work around it. The idea here is to let the server handle security by sending unique data via HTTP requests to the user. If we assume you have `Access Control` on your site, then we are guaranteed that these "keys" only end up with the user. Since `SHA-512` produces some pretty long and random string, we can assume us relatively safe from `Brute Force` attacks. There are some methods to identify the user (see the links), the best overall defense is to delegate to the server like this. – Emil S. Jørgensen May 30 '16 at 12:14
  • $secretHandshake should be saved in session. – jcubic May 30 '16 at 14:11
  • 1
    @jcubic I agree completely. My examples above is more on a pseudo code level because implementation could be drastically different if, for instance, Leonardo were to use WordPress. – Emil S. Jørgensen May 30 '16 at 14:27