Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for securing return to previous page after login or back link url

Tags:

security

php

I found many way for redirect to previous page after login and example :

  1. $_GET - need to validate
  2. $_SESSION - will override the value if using multiple tabs
  3. $_SERVER['HTTP_REFERER'] - it's sent by the browser to the server

On form we can use

<form action="/process/?return=/previous/page/?id=123" method="post" />

or using hidden input.

<input type="hidden" name="return" value="$_GET or $_SESSION or $_SERVER" />

May I know what is the best practices to secure the return value?

like image 688
user1286499 Avatar asked Nov 05 '22 02:11

user1286499


2 Answers

The most common practice (also on e-commerce sites in payment checkout) is to have a hidden input with the URL to redirect to:

<input type="hidden" name="return" value="<?php echo($_SERVER['REQUEST_URI']); ?>" />

It seems to be secure enough for most people...

like image 131
Alfred Godoy Avatar answered Nov 07 '22 22:11

Alfred Godoy


Well, there are three solutions that come into my mind:

The best solution would be to create a whitelist containing all possible urls, but that is unmanagable in most cases. If you have the possibility you can auto-create the urls (maybe from database?). Neverthless:

<?php
  $whitelist = array('url1', 'url2',...);

  $referer = $_POST['referer'];

  if(in_array($referer, $whitelist))
  {
     header('Location: '.$referer);  // redirect to target
  }
  else
  {
     header('Location: /');  // redirect to default page
  }
?>

The second solution that comes into my mind would be to check the url using regular expressions (depends from where your user can come from).

The third solution seems to use a secret key for generating a token, that prevents the user from form-tampering:

<?php
    $referer = htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES); // request-url or get value whatever you like
    $secret = 'sfhuwefwejori234'; // key of your choice
    $token = sha1($secret.$referer); 
?>

<form action=....>
  <input type="hidden" name="referer" value="<?php echo $referer; ?>" />
  <input type="hidden" name="refToken" value="<?php echo $token; ?>" />
...

On the target page, before redirecting the user, recreate the token with the passed value and check if it is correct:

<?php
  $referer = $_POST['referer'];
  $token = $_POST['refToken'];
  $secret = 'sfhuwefwejori234';  // SAME key as above, do never include this into a form, user cannot know this key

  $originalToken = sha1($secret.$referer);

  if($originalToken == $token)
  {
     header('Location: '.$referer); // redirect user
  }
  else
  {
     header('Location: /'); // Redirect to default page
  }
?>

This will protect you from form tampering and cross-site-scripting.

Cheers!

like image 29
AlexFr. Avatar answered Nov 07 '22 20:11

AlexFr.