Roger
Roger

Reputation: 8586

PHP: help secure / filter ajax calls

I am trying to find a way to filter ajax calls in order to add a fine layer of security to my applications. Does the code bellow make any sense?

function is_ajax(){//Help Secure Ajax Calls
    if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest') return;
    else die;//no ajax
}

My dream is only let a file inside my server (htm or php) to access another php file via ajax.

I wonder if the code bellow would not do better:

if(strpos($_SERVER['REQUEST_URI'],'http://')) die;//Help Secure From URL Include Attacks

Thanks.

Upvotes: 0

Views: 2314

Answers (4)

user2898514
user2898514

Reputation: 27

I think for a little more security you could decode your secret string after you encode it. then echo than decoded string in php and then copy it. then on the the $valid variable

$valid = (base64_decode($_REQUEST["signed"]) === "blahblahblah that you copied from php");

Upvotes: 0

rmorero
rmorero

Reputation: 596

Since the AJAX call is always made from the browser, the request is not coming from your own server, but the client machine. Even if you set custom headers, these can easily be manipulated on the client side.

If your goal is to only allow your own scripts to access the script containing the ajax content, I'd recommend generating a token string that is only valid for a certain requested url and a specified time.

Quick and dirty example:

Script requesting the AJAX resource:

$secret ="ABC1232";

$item = array(
  "time"=>time(),
  "token_id"=>"<page_url>"
);

$signed = base64_encode(hash_hmac("sha256",json_encode($item),$secret));
$item = base64_encode(json_encode($item));

$ajax_url = "myscript.php?signed=$signed&item=$item";

AJAX Resource, check the token is valid

$item = json_decode(base64_decode($_REQUEST["item"]));

$timeout = 3600;

if($item->time < (time()-$timeout)){
  die("Invalid token - timeout");
}

if($item->token_id !== "<page_url>"){
  die("Invalid token - page url");
}

$secret ="ABC1232";
$valid = ($_REQUEST["signed"] === base64_encode(hash_hmac("sha256",json_encode($item),$secret));

if(!$valid){
  die("Invalid token");
}

Upvotes: 7

robjmills
robjmills

Reputation: 18598

Assume that anything that can be requested by AJAX will also be accessed directly and you will be in a much safer place. You really should consider why you would only ever want something to be accessed via AJAX in the first place. The HTTP_X_REQUESTED_WITH header is unreliable and easily spoofed so it provides no real security anyway.

Upvotes: 1

Michael D. Irizarry
Michael D. Irizarry

Reputation: 6302

Your Ajax is as secure as your application layer. Ajax is just client side code accessing server side code. There is probably no way in securing it the way you want since anyone can emulate Ajax calls from within any language by just modifying the request headers. One more thing most ajaxified frameworks do include HTTP_X_REQUESTED_WITH but it's not 100% reliable.

Just secure your server code and your good to go. If you really want to at least let your server code know that it's receiving an ajax call, use a parameter on the request.

Upvotes: 4

Related Questions