$_SERVER['HTTP_REFERER'] and cookies

4.2k Views Asked by At

I read, both on SO and other sites, that $_SERVER['HTTP_REFERER'] is something we, as programmers, should always avoid. Reading the PHP manual we encounter these lines:

The address of the page (if any) which referred the user agent to the current page. This is set by the user agent. Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. In short, it cannot really be trusted.

Considering "user agents" things such as Web Browser (Safari, Chrome, Opera, Firefox, basically they are all), the manual tell us that this variable may be changed by them. Here it comes my first question:

Question 1: Why should "users agent" modify this parameter? What are the reason for a web browser not to set this parameter?

It's just inquisitiveness, and i'll not use $_SERVER['HTTP_REFERER']. From my latest statement, it's oblivious that, if we do need of such a function, we need to figure something out. The first thing that comes in my mind is a cookie solution, in which we do something like:

setcookie('latest_page', __FILE__, 60 * 60 * 24 * 7);

And then, based on how you prefer to do it, you can recover what you need. Here it comes the second and last question:

Question 2: Is this way the best? Are there any way to improve it?

7

There are 7 best solutions below

1
On BEST ANSWER

There is no reason to avoid HTTP_REFERER. Just when using it, be aware that it's not always set, and that it can be freely manipulated by the client, so it is untrusted data.

The vast majority of clients sets the variable, and does so correctly.

The main reason for blocking it is privacy: For example, when opening an E-Mail in a web mail client, links to external images would carry the web mail service's address in the HTTP_REFERER header. That's why GMail and Yahoo make efforts to block it.

The workaround you suggest works only for movements within the same site, and will break if the user has more than one tab/browser window open with which they browse your site. If you need to know the referring page, the superior method is to add a GET parameter like

<a href="otherpage.html?from=thispage.html">

Edit: One example where relying on HTTP_REFERER is dangerous would be showing a live-updated list of referring sites on your main page ("Visitors came from...") it would be easy to smuggle arbitrary URLs into that list by visiting your site with a fake HTTP_REFERER set.

0
On

Well, remember that like any header the client sets, it can be tampered with. So use it wisely.

0
On

Cookie based solution is not the best nor the solution at all.
Nobody using it, because a cookie is a site-wide matter.

Most of time "go back" link is just useless. Every modern browser has a Back button.
If you want to implement it anyway, just make it the same way as it's implemented on the other sites.

0
On

Http referrer can be dangerous if it has to do something with your website database if not sanitized. It is also completely client side, so there is chance that someone can exploit it. But besides that there is nothing wrong with it.

Cookies can be changed too. If you want something that can not be changed by user go with Php Sessions.

0
On

Why should "users agent" modify this parameter? What are the reason for a web browser not to set this parameter?

The HTTP referrer can be used to profile a user’s behavior because you can see the page that referred to the current page. It can also unveil sensitive data such as a session ID in the URL to third party sites. This is why many web sites use dereferrer as a single exit page for all external links.

That are the main reasons why some user agents don’t send a HTTP referrer at all. In opposite to that, HTTP referrers are only send when you actually follow a link or submit a form on a page. Any request that was triggered otherwise (HTTP redirect, direct request via location bar/bookmark) is not a referrer.

Is this way the best? Are there any way to improve it?

Doing it that way won’t work if you have opened a website in multiple tabs/windows. You would need an identifier for each page request so that you can identify the page that actually referred this one:

  • Current requested page: /index.html
  • Request ID of current requested page: 12345

Each link will then contain the request ID to identify the request that referred to the next page:

<a href="/foo.html?request-id=12345">
<a href="/bar.html?request-id=12345">

By doing this also on forms and by additionally using an unpredictible value for the page request ID you can also make CSRF attacks more difficult.

0
On

If you need a go back link you should use this:

<a href="javascript:history.back();"><< Go Back</a>

OR

<a href="javascript:history.go(-1);"><< Go Back</a>

This is the best way to provide a go back link to users

0
On

Question 1: Why should "users agent" modify this parameter? What are the reason for a web browser not to set this parameter?

Well, web browsers don't really have a reason not to set this. You've been told to avoid it because of the same reason some browsers would avoid it, wich is misuse. Like saving important session info in the URL.

You shouldn't try and avoid it using, you should just use it responsibly. And not have to use any 'gimmick'. For example, its very common to use it as a 'Resume' navigation. Say for instance someones session expired using your webpage. You could send them to the login credentials page. And then redirect them to the requested URL.

The same goes when they are trying to first access your webpage without passing through the login screen.

  1. Start browser (No info saved in cookies o sessions)
  2. Go to www.YourApp.com/restrictedZone.php
  3. Redirect to login
  4. Login challenge passed
  5. Redirect to restricted zone instead of 'index.php' or 'home.php'

You should just make sure you check for a valid session on ALL of your 'restricted zone' pages.