Search code examples
javascriptphpcookiescsrf-protection

Be sure my php has been invoked by my javascript on my web page


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.


Solution

  • 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.