Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any need to sanitize a $_POST value before using it in a PHP header (for redirecting)

Can I use a posted value in a PHP redirect header safetly without checking it:

header( "Location: $base".$_POST['return'] ); // $base is set to the base of the site

(If the user would somehow manipulate return to a file that doesn't exist it would simply return a nice 404 message)

Is there any danger in doing this? Is there anything the user can set it to that can compromise the system or in any way do damage?

like image 534
Chaim Avatar asked Nov 27 '11 14:11

Chaim


People also ask

How to use header in PHP for redirect?

To create a PHP redirect, you first need to write your header() function. This begins with header(). Next, define the Location response-header field with the URL or file name where you want to redirect users and search engines. Place that within the parentheses.

How redirect URL in PHP?

Answer: Use the PHP header() Function You can simply use the PHP header() function to redirect a user to a different page. The PHP code in the following example will redirect the user from the page in which it is placed to the URL http://www.example.com/another-page.php . You can also specify relative URLs.

What is header () in PHP?

The header in PHP is a PHP built-in function for sending a raw HTTP header. The HTTP functions are those that manipulate information sent by the webserver to the client or browser before it sends any further output. The header() function in PHP sends a raw HTTP header to a client or browser.


2 Answers

The header() function is no longer vulnerable to HTTP Response Splitting. The only vulnerability you have to worry about is OWASP a10 - unvalidated redirects and forwards.

Providing a $base of anything other than the null string will prevent an attacker from forwarding a user to a remote domain, which could be useful for Phishing. Redirecting to the same domain could be useful to the attacker if are checking the referer as a form of CSRF prevention, but that is a weak form of protection that you really shouldn't be using anyway. Even with a base, the attacker can change the path by supplied a value like: /../../../admin.php, but this is still relative to the originating domain which in most cases is safe.

One great way to deal with unvalidated redirects is to avoid the problem entirely by not using a REQUEST variable. Instead store it in a $_SESSION['redirect'], and use that for the next request. To be a bit more robust, you could say $_SESSION['redirect_checkout'], or something page specific.

Another option is to use a white list, create a list of all values you would like to accept, and make sure the user supplied value is in your list.

like image 124
rook Avatar answered Sep 21 '22 00:09

rook


Yes, absolutely! Don't trust any $_GET or $_POST values anytime!

Suppose a third party site posts the form. It may post whatever address.

A simple solution would be not to include the address, but a md5() hash of the address into the form. Once the form gets posted, it's the task of your script to map the hash to an actual address and then emit the Location header.

My other post might be of interest.

You might argue, that your app is bullet-proof. Why shouldn't I pass an URL directly?

In fact, even well-designed applications aren't that bullet-proof. Step back and try to remember your last 'Ah, I forgot something. Let's fix it' event.

Did you check at each point control each and any condition?

  • User clicks on a web-form submit-button twice. Thus controller runs twice.
  • User presses F5 an resubmits the last updating controller twice.
  • User somehow manipulated parameters and a controller gets called with off values passed in.

Therefore, I propose to not pass links or other parameters directly or unprotected / unvalidated.

@Col. Shrapnel: I'm fully aware, that any URL at any point could be submitted to a web-app. That's trivial.

Nevertheless, at a given point of control flow, there are certain acceptable next states of control flow.

To ensure, that only those next control-flow states get reached, I propose to validate.

A more general approach

In fact, my recently updated internal framework never passes any parameters as GET or POST parameters from request to request. All parameters are saved and retrieved from a user session [inside a so called Flow, a part of a bigger control flow].

Using the framework, only one single parameter - the FlowID - gets passed around. If the framework doesn't find the FlowID in the session's flow-store, the framework throws an exception and the dispatcher emits an error message.

like image 28
SteAp Avatar answered Sep 23 '22 00:09

SteAp