tags:

views:

343

answers:

2

Hi all:

This is the first time I am working for a front-end project that requires server-side authentication for AJAX requests. I've encountered problems like I cannot make a call of session_start as the beginning line of the "destination page", cuz that would get me a PHP Warning :

Warning: session_start() [function.session-start]: 
Cannot send session cache limiter -
headers already sent (output started at C:\xampp\htdocs\comic\app\ajaxInsert
    Book.php:1)
in C:\xampp\htdocs\comic\app\common.php  on line 10

I reckon this means I have to figure out a way other than checking PHP session variables to authenticate the "caller" of this PHP script, and this is my approach :

I have a "protected" PHP page, which must be used as the "container" of my javascript that posts the form through jQuery $.ajax(); method

In my "receiver" PHP script, what I've got is:

<?php
define(BOOKS_TABLE, "books");
define(APPROOT, "/comic/");
define(CORRECT_REFERER, "/protected/staff/addBook.php");

function isRefererCorrect()
{
    // the following line evaluates the relative path for the referer uri, 
    // Say, $_SERVER['HTTP_REFERER'] returns "http://localhost/comic/protected/staff/addBook.php"
    // Then the part we concern is just this "/protected/staff/addBook.php"
    $referer = substr($_SERVER['HTTP_REFERER'], 6 + strrpos($_SERVER['HTTP_REFERER'], APPROOT));
    return (strnatcmp(CORRECT_REFERER, $referer) == 0) ? true : false;
}

//http://stackoverflow.com/questions/267546/correct-http-header-for-json-file
header('Content-type: application/json charset=UTF-8');
header('Cache-Control: no-cache, must-revalidate');

echo json_encode(array
    (
        "feedback"=>"ok", 
        "info"=>isRefererCorrect()
    ));
?>

My code works, but I wonder is there any security risks in this approach? Can someone manipulate the post request so that he can pretend that the caller javascript is from the "protected" page?

UPDATE:

just realized I can let javascript from the secured page generate a unique token per ajax request, and use the passed token value to authenticate whether it is a "genuine ajax call" from the secured page

Will this be much better? Or should I just encrypt the content of the post request?

UPDATE AGAIN :

After two hours of looping through the included pages, I finally noticed that this weird situation was caused by my PHP page encoding...

I gave Notepad++ a try and carelessly chose the page encoding as UTF-8 with Byte Order Marker, so I kept getting the warning message due to the "weird" interpretation of this line:

<?php

A good lesson for me...

Many thanks to any hints or suggestions.

+2  A: 

Technically seen, somebody can send you a request with referrer being 127.0.0.1, 0.0.0.0 or pretty much whatever they want without ever touching the site; so yeah, relying on it might not be the best approach.

Also: You CAN and SHOULD use php_session - you simply have to call session_start(); BEFORE anything else sends ANYTHING (as the error clearly states: headers already sent). Judging from the error

(output started at C:\xampp\htdocs\comic\app\ajaxInsert Book.php:1)

this might simply be a newline at the beginning of the file i.e

//empty line
<?php
//code

Ad. Update: It'll probably make things more secure; given the page which creates the token can only be accessed by people with the required permissions; it seems ok. Though even after reading your comment I believe you have some unneccessary whitespace somewhere, as sessions seem a perfectly fine way to authenticate the AJAX request.

Robus
@Robus : yeah, I've checked the source code many times and am pretty sure the cause of the problem is because : my javasript is loaded from a secured page which already uses session_start() to make sure only authenticated staff member can access this protected page. In fact, the "destination page" works fine to insert book into DB, just in this page it cannot use session_start()...
Michael Mao
wish i could upvote this. I'm outta votes for today :(
Jacob Relkin
@Michael MaoYou have to call session_start(); every time a new page is loaded, thus even if an earlier page already used it; it should'nt cause trouble.
Robus
@Robus : you just made a good point... I should go back to check the "stack" of included php pages and find it out, tomorrow... It is 1am in Sydney and I've been in front of my laptop for 10+ hours :(
Michael Mao
@Robus: Problem solved, it was the PHP page encoding (UTF-8 with Byte Order Marker) that caused this weird problem:(
Michael Mao
A: 

may be there is a Unicode Signature(BOM). Check it.

zol