Jim Lawless' Blog


Thwarting HTTP Referer Trackbacks

Originally published on: Thu, 15 Oct 2009 02:54:15 +0000

Unless you've configured your browser with privacy plug-ins, your browser passes the address of the current page to each target link you click in a header known as HTTP_REFERER. "Referer" is spelled incorrectly by convention. It was spelled incorrectly during early designs of the HTTP protocol.

One can easily change their own browser to squelch the transmission of the referer, however visitors on a web site may not take the same precautions. What if you have a very personal blog that has a mix of some personal items that you only want a handful of friends to see along with some fun links to other sites?

Anyone viewing your site might click on a link transmitting your private blog page to the site ( where it might be made public. )

Please try this: click the link below. You should see a reference to this blog page.

ttp://www.mailsend-online.com/wp/referring_page.php

Here's the PHP code for the page:

referring_page.php


<html><head>
<!-- By Jim Lawless
     This code is in the public domain
-->
<title>Referring Page Check</title></head>
<body>
<P>
Your referring link is:
<?php
   echo "<a href=\"", $_SERVER['HTTP_REFERER'],"\">",$_SERVER['HTTP_REFERER'],"</a>";
?>
<p>
</body></html>

So, if you have a couple dozen people reading your blog, chances are that one of them will click on a link that exposes your blog URL to the outside. Of course, this can be protected by using a login system, but there's another way that might be just as effective that does not require a client to log in to your system.

Normally, a browser issues an HTTP GET command to retrieve a web page. Any time you type a URL into an address bar or click an anchored link, your browser issues a GET to retrieve the given page.

When forms are filled out, the browser often uses the HTTP POST command ( if specified in the form's METHOD attribute. ) Fields often are sent in name/value pairs during a POST.

Fields can also be sent during a GET request, but they appear on the URL line itself. Such a line might look like:


http://some.url?parm1=this&amp;parm2=that&amp;parm3=other

These URL's with the parameters are passed in their entirety in the HTTP_REFERER header during a GET. They also often show up in web server logs. However, fields presented during a POST are not carried in the referer.

If we create a page that only displays the private content if a POST was issued and if a special field contains a certain value, any links that the client clicks on will carry only the URL itself without parameters.

If anyone tries to copy that link into a browser's address bar or if they are clicking it from some sort of referring-page list, they will run into two problems.

  1. They're issuing the request using a GET
  2. They will have no idea what the special field is supposed to contain

Please consider the following sample PHP documents: ( the first two are actually pure HTML documents... )

refer1.php


<html><head>
<!-- By Jim Lawless
     This code is in the public domain
-->
<title>Referer test 1</title></head>
<body>
Show referring page:
 <a href="referring_page.php">
 referring_page.php</a>
<p>
Go to lead-in page:
 <a href="refer2.php">
 refer2.php</a>
<p>
</body></html>

refer2.php


<html><head>
<!-- By Jim Lawless
     This code is in the public domain
-->
<title>Referer test 2</title></head>
<body onload="doit()">
<noscript>
You must enable JavaScript to see this site.
</noscript>
<form ID="myform" NAME="myform"
  ACTION="refer3.php" METHOD="POST">

<input TYPE="hidden" NAME="mycode" VALUE="1234">
</form>

<script TYPE="text/javascript">
   function doit() {
      document.getElementById("myform").submit();
   }
</script>
</body></html>

refer3.php


<html><head>
<!-- By Jim Lawless
     This code is in the public domain
-->
<title>Page 3</title></head>
<body>
<?php
   if(strcmp($_POST["mycode"],"1234")==0) {
?>
<h2>Hey, you can see the good stuff!</h2>
<p>
Try going here:<br />
<a href="referring_page.php">referring_page.php</a>


<?php
   } else {
?>
<h2>Nothing to see here. Move along.</h2>
<?php
   }
?>
</body></html>

Let's try out this code. Please click on this link. It should open in a new window, so please adjust your popup-blocking software accordingly.

http://www.mailsend-online.com/wp/refer1.php

Click on the referring_page.php link.

You should see that you had originated from the refer1.php page. Click the link on this page to go back there.

You just backtracked to a calling page by using a referer!

Now, click the refer2.php link.

When you do this, you might note that the URL in your browser's address bar quickly changes from refer2.php to refer3.php.

If you look at the code in refer2.php, you'll see that it contains a small JavaScript function that triggers when the onLoad event occurs. This function forces the HTML form on the page to be invoked via a call to submit(). The HTTP method defined in the form is POST. Data will be POSTed to the target refer3.php page.

Once in refer3.php, you'll note that you can see the message "Hey, you can see the good stuff!"

Examination of the source code to refer3.php shows that we look for a POSTed field called mycode that must have a value of "1234" or the page will render differently.

Try clicking on the referring_page.php link. You'll see the reference to refer3.php. Click it.

Now, you should see the message "Nothing to see here. Move along." Because you issued a GET when you clicked the link, no POST operation occurred. Note the PHP else block toward the bottom of the refer3.php script. This is the block of HTML that is rendered if the page is visited without going through a POST with the special code.

This technique will allow one to display a different page to most casual visitors who happen upon a URL ( including search-engine robots and spiders ) and will allow special visitors who know the URL to a lead-in page ( refer2.php, in our case ) to see special content.

Please note that this hack is just for fun. Although you could use it to supplement a real security system, sensitive data should be handled much more thoroughly than by using the technique above. Security through obscurity isn't secure.

The technique above might be useful if you'd like to keep stuff out of most prying eyes and search-engines that backtrack through the referer, but it isn't foolproof. All someone has to do is leak the lead-in page address and then everyone could get in.

Unless otherwise noted, all code and text entries are Copyright ©2009 by James K. Lawless

del_icio_us Save to del.icio.us
stumbleupon Save to StumbleUpon
digg Digg it
reddit Save to Reddit
facebook Share on Facebook
twitter Share on Twitter
aolfav More bookmarks



Previous post: TAP : A Command Processor Library
Next post:Preventing Windows Screen-Saver Activation


Search this Blog (and site)

Search this Site with PicoSearch


Subscribe to this Blog

 Subscribe!


Contact Me

Email: jimbo@radiks.net


Follow me on Twitter

http://twitter.com/lawlessGuy


Recent Posts

Mad Schemes : Learning Lisp via SICP

Auto Save Clipboard Images Redux

Extending SpiderMonkey JavaScript on Windows

Rhino JavaScript to EXE with launch4j

Compiling Rhino JavaScript to Java

Directory Traversal in Rhino JavaScript

Taking Shape

We've Moved!


Popular Posts

A Command-Line MP3 Player for Windows

Auto Save Images from the Clipboard

Java in a Windows EXE with launch4j

An Interview with Tom Zimmer: Forth System Developer

Setting Windows Console Text Colors in C


Random Posts

Locking a Windows Session

Twimmando: A Command-line Twitter Client

WSH JavaScript Includes

Obfuscated Ruby

A Lightweight Alternative to Windows Shortcuts

Java in a Windows EXE with launch4j

Directory Traversal in Rhino JavaScript

The Protection Racket

Switching a Console Window to Full Screen or Windowed Mode

Internet Protocols and Rhino JavaScript


Full List of Posts

http://www.mailsend-online.com/bloglist.htm


Blogroll

MicroISV on a Shoestring
DadHacker
The Bottom Feeder
Writin' That Code!
The Recursive ISV
The Thomsen Blog
Prototypically Speaking
The Reinvigorated Programmer