Jump to content

Recommended Posts

Hey y'all.

 

I'm a bit brain-fried and afraid I'm overlooking or forgetting something simple on this, and wanted some opinions/experiences. I'm working on a home-spun CMS using a router and mod_rewrite. Now, the back-end is clearly going to have forms that allow the manipulation of the data on the site, and I want to use the PRG pattern to avoid possible duplicate requests. However, we all know that PHP_SELF isn't safe, not to mention it returns index.php every time due to the router/rewrite combo. $_SERVER['REQUEST_URI'] returns the path I need to refresh properly, but I just want to make sure that using it in a 303 redirect header is fairly safe. I'm planning on using htmlspecialchars() and checking the returned value for quotes and/or semicolons, but honestly I've got enough other things to do to not want to waste my time writing that if it's innately an unsafe or bad solution.

 

Any opinions, ideas, thoughts, or rants?

htmlspecialchars() is only for putting stuff with special characters into HTML. As the name might suggest.

 

The REQUEST_URI must necessarily be safe if your web server was able to accept it and have PHP execute properly for it. The Location header itself doesn't have any special structure besides "Location: URI".

Thanks for the input!

 

Really, I was looking to (ab)use htmlspecialchars() - in this case - as a last-gasp attempt to at least scramble any tag-based XSS attacks that got through. I figured that

<script>bad stuff</script>

would better than an  unexpected

<script>bad stuff</script>

regardless where it landed. It's probably naive, admittedly - I'm not a security expert by any means. I do what I can to make what I code as safe as possible and try to keep up with the latest information; hence the question.

 

My concern is this - I gather that $_SERVER['PHP_SELF'] can be spoofed pretty easily and shouldn't be used; is there the same level of concern with $_SERVER['REQUEST_URI']? For instance, if a (clearly really, really bored) hacker decides my little site is worth the effort, he or she can fake a post request to my endpoint. Assuming somehow that he or she can fake or grab a correct nonce and set of database-verified session credentials, would $_POST['REQUEST_URI'] then show my form address or his or her fake request address? And would it matter that much either way?

 

Really, what it comes down to is that I've never had an interest in malicious hacking so I'm not even really sure how one would go about doing some of this stuff, which makes it difficult to test for in a safe development environment. I've read books and articles on the topic and have some basic manual testing methods that I use, but I want to be better at it...

Let's be clear: I'm only talking about using the value within a Location header. Nothing else.

 

Yes, kinda, PHP_SELF and REQUEST_URI can be "spoofed" in the sense that someone can manipulate the data. They can forge a request using any valid URI they want to your server. However if they use an invalid URI then the server will reject it. Immediately. Because it's invalid.

So if your PHP has the value of REQUEST_URI then that necessarily means the URI is valid: the server accepted it and figured out that it should be routed to your PHP script. Is it exactly what you want? Not necessarily: odds are someone could add new query string parameters and your script wouldn't care, for example. However the resulting URI must still be valid, which is why you can put it into a Location.

 

Can you do the same with PHP_SELF? I don't remember if it is a URI-decoded value. I think so. But it doesn't include the query string so you wouldn't want it anyways (at least not when you could use REQUEST_URI instead, which does).

The Location header actually isn't as safe as one might think. For example, all PHP versions up until 5.1 were vulnerable to Response Splitting Attacks where the attacker could inject a CR LF sequence after the URL and then either add new headers (e. g. to overwrite critical cookies) or manipulate the response body.

 

Also note that neither PHP_SELF nor REQUEST_URI are necessarily valid. Webservers are extremely fault-tolerant, which means they accept anything as long as they can make sense of it. For example, I could easily inject raw control characters into the REQUEST_URI. This absolutely shouldn't happen as it violates even the most basic syntax rules for URLs, but it's still possible.

 

So I'd take a much more conservative approach. Instead of relying on the webserver and PHP to give you a safe URL, you should assemble the URL. That is, pick the target path, make a whitelist of permitted query parameters and use http_build_query() to make sure the URL is actually valid:

<?php

const TARGET_PATH = '/path/to/target';

$permitted_target_parameters = [
    'foo' => null,
    'bar' => null,
];



$filtered_target_parameters = [];

foreach ($_GET as $parameter => $value)
{
    if (array_key_exists($parameter, $permitted_target_parameters))
    {
        $filtered_target_parameters[$parameter] = $value;
    }
}

$target_url = TARGET_PATH.'?'.http_build_query($filtered_target_parameters);

header('Location: '.$target_url);
exit;
Edited by Jacques1
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.