Page 1 of 1
Q: header redirect...not full url. security problem?
Posted: Wed Oct 18, 2006 11:27 am
by jmut
Hi,
I think this topic is discussed but I just could not find anything

Can anyone point out how is
Code: Select all
header("Location: http://www.example.com/login.php");
different from
Code: Select all
header("Location: login.php"); //what is wrong with this approach.
Is it security problem or something.
Thanks a lot
Posted: Wed Oct 18, 2006 11:31 am
by Obadiah
i wouldn't say there is anything wrong with it...just one will go to a sit and the other to a local place on your machine or server....are you having problems with the latter?
Posted: Wed Oct 18, 2006 11:31 am
by Luke
not all browsers support relative urls. use the FULL url...
http://www.yoursite.com/blabla.html
http://www.w3.org/Protocols/rfc2616/rfc ... l#sec14.30
W3C wrote:Location is that of the new resource which was created by the request. For 3xx responses, the location SHOULD indicate the server's preferred URI for automatic redirection to the resource. The field value consists of a single absolute URI.
Posted: Wed Oct 18, 2006 11:32 am
by Oren
From the PHP manual:
Note: HTTP/1.1 requires an absolute URI as argument to Location: including the scheme, hostname and absolute path, but some clients accept relative URIs
Posted: Wed Oct 18, 2006 12:02 pm
by Ollie Saunders
Actually I think it has to be a really old browser for it to be an issue. I still use absolute URLs but I'm not sure how much it really matters these days. You can always do this:
Code: Select all
function redirect($relativeUrl)
{
header('Location: http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['SCRIPT_NAME']) . $relativeUrl);
exit;
}
Posted: Wed Oct 18, 2006 12:44 pm
by jmut
ole wrote:Actually I think it has to be a really old browser for it to be an issue. I still use absolute URLs but I'm not sure how much it really matters these days. You can always do this:
Code: Select all
function redirect($relativeUrl)
{
header('Location: http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['SCRIPT_NAME']) . $relativeUrl);
exit;
}
also for the "http" part.......
Code: Select all
( isset($_SERVER['HTTPS'])) ? 'https' : 'http';
Ok thanks all. So I guess it does not matter that much. I though it might be security concern or something.
But really...I guess it is an old browser not responding issue.
Thanks again.
Posted: Wed Oct 18, 2006 12:53 pm
by Ollie Saunders
Great stuff. I'm going to put this in my library. Any other potential problems people can think of?
Posted: Wed Oct 18, 2006 1:17 pm
by feyd
$_SERVER['HTTPS'] can be defined but not in use (you're not running in secure) on some servers.
Check Burrito's geturl() function for an example.
Posted: Wed Oct 18, 2006 1:53 pm
by jmut
feyd wrote:$_SERVER['HTTPS'] can be defined but not in use (you're not running in secure) on some servers.
Check Burrito's geturl() function for an example.
you mean servers like apache vs IIS for example....or even different configs with apache.
where can I see this geturl() function

Posted: Wed Oct 18, 2006 1:57 pm
by d3ad1ysp0rk
I don't see Buritto's, but here's a geturl function in the Code Snippets forum (

)
viewtopic.php?t=24358&highlight=geturl
Posted: Wed Oct 18, 2006 2:13 pm
by feyd
Posted: Wed Oct 18, 2006 5:43 pm
by Ollie Saunders
Code: Select all
/**
* Preform a HTTP(S) redirect. Supports relative or absolute path.
*
* @param string $input
*/
function OSIS_Redirect($input)
{
static $protocol = null;
if ($protocol === null) {
if (empty($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) == 'off') {
$protocol = 'http';
} else {
$protocol = 'https';
}
}
static $port = null;
if ($port === null) {
$ports = array('https' => 443, 'http' => 80);
if ($_SERVER['SERVER_PORT'] != $ports[$protocol]) {
$port = ':' . $_SERVER['SERVER_PORT'];
} else {
$port = '';
}
}
if ($input[0] == '/') { // absolute
$path = array('');
} else { // relative
$path = explode('/', dirname($_SERVER['SCRIPT_NAME']));
}
$input = explode('/', $input);
foreach ($input as $part) { // resolve to absolute
if ($part == '.' || $part == '') {
continue;
}
if ($part == '..') {
array_pop($path);
continue;
}
$path[] = $part;
}
$path = implode('/', $path);
return "Location: $protocol://{$_SERVER['HTTP_HOST']}$port$path";
}
These pass:
Code: Select all
public function testRedirect()
{
$originalServer = $_SERVER;
$_SERVER['HTTP_HOST'] = 'zim.com';
$_SERVER['SCRIPT_NAME'] = '/foo/bar/gir.php';
unset($_SERVER['HTTPS']);
$this->assertEqual(OSIS_Redirect('dib.php'), 'Location: http://zim.com/foo/bar/dib.php');
$this->assertEqual(OSIS_Redirect('..//gaz.php'), 'Location: http://zim.com/foo/gaz.php');
$this->assertEqual(OSIS_Redirect('/abs.php'), 'Location: http://zim.com/abs.php');
$this->assertEqual(OSIS_Redirect('../.././pig.php'), 'Location: http://zim.com/pig.php');
$this->assertEqual(OSIS_Redirect('dad/../../../gaz.php'), 'Location: http://zim.com/gaz.php');
$_SERVER = $originalServer;
}
By no means an exhaustive test. I still haven't fully got into the habbit of writing tests first so I butchered it with all that portability stuff without any tests. Hmmm, I'll do some more later.
Oh yeah and I'm posting this here for comments and criticism. If someone wants to finish testing it for me that would be nice too
