caddmngr has asked for the wisdom of the Perl Monks concerning the following question:

hello oh mighty powerful PerlMonks.... I seek your wisdom and guidance in a most difficult situation.

I have two websites on two separate servers/locations - we want to make one of them an extension to the other by only allowing visitors access to Site B if they've come from a link at Site A, otherwise they get a custom error page.

I have it all worked out fine, however, a problem has crept in. The link on Site A to Site B is from a secure connection, and apparently https does not send the variable $ENV{'HTTP_REFERER'}!!?? Is there a way around this, or might one of you expert priests of the highest order of perl have a better solution for me please?

I was thinking of tagging an identifier onto the end of the link string, but that could easily be faked unless I went with encrypt/salted string - but what a pain. There has to be an easier way! If there is, Im sure I'll discover it here.

*bows to the gods
Thank you, fathers,
Chris

Replies are listed 'Best First'.
Re: Get Referral From SSL
by Corion (Patriarch) on Jul 20, 2005 at 11:41 UTC

    Relying on $ENV{'HTTP_REFERER'} is not secure anyway, so you might as well go and tack something to the requested URL. It is trivial to fake the referrer. You could, for example, store the handed-out URLs in a database and only recognize these as valid, as a solution.

Re: Get Referral From SSL
by dorward (Curate) on Jul 20, 2005 at 11:42 UTC

    The referer is an optional header, is often munged, and is easily forged. It can not be depended on.

    I would probably generate an authentication token to give to the client on site A, then have server A inform server B that it now existed (or let them use a shared database).

Re: Get Referral From SSL
by jhourcle (Prior) on Jul 20, 2005 at 12:53 UTC

    What you are seeing is actually a good thing -- this means that the clients people are using are following the HTTP recommendation::

    From the HTTP/1.1 specs, section 15:

    5.1.3 Encoding Sensitive Information in URI's

    Because the source of a link might be private information or might reveal an otherwise private information source, it is strongly recommended that the user be able to select whether or not the Referer field is sent. For example, a browser client could have a toggle switch for browsing openly/anonymously, which would respectively enable/disable the sending of Referer and From information.

    Clients SHOULD NOT include a Referer header field in a (non-secure) HTTP request if the referring page was transferred with a secure protocol.

    Depending on how sensitive the fact is that someone was redirected to the insecure site from the secure site, you could encrypt a timestamp with a two-way key, that both servers know, so the receiving server can decrypt the timestamp, and check if it's current.

Re: Get Referral From SSL
by themage (Friar) on Jul 20, 2005 at 12:52 UTC
    If you don't have access from server A to server B, I'ld simply use some key appended to the end of the URL, like this:

    On server A (using mason):
    use Digest::MD5 qw(md5_hex); my $ip=$r->connection->remote_ip(); my $url="/gotohere/"; my $basekey="somespecialkeyequalinsiteaandsiteb"; my $sid=md5_hex("$ip;;$url;;$basekey"); $url="http://www.siteb.com$url?sid=$sid"; $r->redirect($url);

    In a autohandler on site B:
    use Digest::MD5 qw(md5_hex); my $sid=$ARGS{sid}; my $url=$r->uri(); my $ip=$r->connection->remote_ip(); my $basekey="somespecialkeyequalinsiteaandsiteb"; my $vsid=md5_hex("$ip;;$url;;$basekey"); if ($sid eq $vsid) { $m->call_next(); }


    The same can be used in CGI or ModPerl, with small changes, I think.

Re: Get Referral From SSL
by caddmngr (Initiate) on Jul 20, 2005 at 22:40 UTC
    Thanks everyone for your input!

    Here's a bit more info which surely will effect the final solution I put together from all your awesome help and advice!

    Site A (the referring site) I have no access to write code for... the only thing they will do for us is adjust the link. I was going to have them tag on an encrypted timestamp, and on Site B, have it validate and allow that timestamp for a period of 5 minutes or so. Exactly like jhourcle suggested - seems the best idea (if not only possible one!)

    Once the user successfully gets to Site B - they have to login to access sensitive areas, so I dont need the most secure method available. In fact, if they were not linking to us from a secure server, using the http referer would have been enough to work.

    The last bit of info... someone mentioned creating a database of valid links we'd allow - trouble with this is we dont even want someone bookmarking the entrance pages.

    How about some sort of Apache or httaccess rules? IP filtering maybe? Is there another method to grab some sort of referrer or IP other than environment variable?

    thanks
    chris