form action="$_SERVER['PHP_SELF']"

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

User avatar
seodevhead
Forum Regular
Posts: 705
Joined: Sat Oct 08, 2005 8:18 pm
Location: Windermere, FL

form action="$_SERVER['PHP_SELF']"

Post by seodevhead »

Hey guys... I have heard various articles over the past couple months state that you shouldn't rely on $_SERVER type variables as they are unpredictable, etc.

But is it safe to do the following for a form on my website?

Code: Select all

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
Or does this leave me open to a security hole? Can a user impart his will on this PHP_SELF variable I am echoing? Thanks for any advice and suggestions. Take care.
User avatar
Burrito
Spockulator
Posts: 4715
Joined: Wed Feb 04, 2004 8:15 pm
Location: Eden, Utah

Post by Burrito »

two notes:

1) There are some $_SERVER variables that you can NOT rely on, but even the ones you can't, I've yet to see return what you're not expecting.
2) I've never understood why people use SELF in a form action. There's no reason for it at all. If you want the form to post to itself, just leave the action attribute out of the tag.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

I think the problem with PHP_SELF is that it is not present on all servers. I tend to use SCRIPT_NAME and SERVER_NAME. Here is some info I found a while back at phpguru:

Everything from $_GET, $_POST, $_COOKIE and $_REQUEST should not be trusted.

From $_SERVER:
* Anything prefixed with HTTP_
* PHP_SELF
* PATH_TRANSLATED
* PATH_INFO
* argv
* PHP_AUTH_USER
* PHP_AUTH_PW
* REMOTE_HOST (though not always, and this is much harder to inject into as it's usually the result of a DNS lookup performed by the web server)

From $_FILES:
* name
* type

From $_ENV when running in CGI mode, contains everything from $_SERVER, so the same keys apply.
(#10850)
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

Here's an interesting article on $_SERVER['PHP_SELF']: XSS Woes.

Anyway, people want to use the variable because it allows them to keep the users at the same URL they where coming from. Using the constant '#' as action does just the same and doesn't have the security issues...
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

There are other reasons to use PHP_SELF outside just forms...
You can clean it before use (usually only for same file references) using:

Code: Select all

$phpself = basename(__FILE__);
$_SERVER['PHP_SELF'] = substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], $phpself)) . $phpself;
As a secondary redundant measure you can also htmlentities() the variable for actual use.
User avatar
techleet
Forum Newbie
Posts: 10
Joined: Wed May 17, 2006 10:51 am
Location: San Jose, CA

Post by techleet »

arborint wrote:Everything from $_GET, $_POST, $_COOKIE and $_REQUEST should not be trusted.

If $_GET, $_POST cannot be trusted, how do you handle forms...?
User avatar
JayBird
Admin
Posts: 4524
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK
Contact:

Post by JayBird »

techleet wrote:
arborint wrote:Everything from $_GET, $_POST, $_COOKIE and $_REQUEST should not be trusted.

If $_GET, $_POST cannot be trusted, how do you handle forms...?
Basically he means you shoul dnever trust user input and all data should be sanitized. Just becuase you are expecting certain values doesn't mean the user will enter them correctly
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

techleet wrote:If $_GET, $_POST cannot be trusted, how do you handle forms...?
Think like a bank..

If you can't trust people to give you the right amount of money, how do you handle the money?

Count it!

When you expect a user to give you a (for example) number from 1-10, make sure that the only thing you accept, by filtering, and cleaning, and similar actions.
User avatar
techleet
Forum Newbie
Posts: 10
Joined: Wed May 17, 2006 10:51 am
Location: San Jose, CA

Post by techleet »

Basically he means you shoul dnever trust user input and all data should be sanitized. Just becuase you are expecting certain values doesn't mean the user will enter them correctly
Ohhhh... of course! You guys scared me for a second there!! :lol:
Last edited by techleet on Wed May 17, 2006 3:10 pm, edited 1 time in total.
User avatar
andym01480
Forum Contributor
Posts: 390
Joined: Wed Apr 19, 2006 5:01 pm

Post by andym01480 »

Facsinating stuff. Read all the links you guys posted.

Follow up question though...

Assuming I have changed

Code: Select all

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
to

Code: Select all

<form action="#" method="post">
as timvw suggests.

that outputs as is.

Couldn't a naughty peep just change the # for the url followed by the bad stuff and then press submit?

Or am i missing the entire point?

The real question, I guess, is how does the attack work?
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Typically the simplest attack would be getting someone to visit the doctored URL containing the exploit. Maybe a forum link, or a PM, or something else. Not everyone checks the full url in their browser status bar before visiting a link.
User avatar
andym01480
Forum Contributor
Posts: 390
Joined: Wed Apr 19, 2006 5:01 pm

Post by andym01480 »

I think you are saying that the attack happens by a third party doing something to PHP_SELF so that when a poor unsuspecting user opens the page with the form the form submit executes the extra code? :oops:

If so then # stops that because the 3rd party can't change the unused PHP_SELF. :wink:

How do they doctor the PHP_SELF - is that something that can only happen on a shared server?

As an aside the status bar can say whatever you want it to say with

Code: Select all

<SCRIPT>
self.defaultStatus ="Whatever I want to say in the status bar"
</SCRIPT>
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

http://blog.phpdoc.info/archives/13-XSS-Woes.html

It's possible to alter the variable using mod_rewrite on Apache. Just edit a valid URL in a specific way to inject an external reference to a javascript file to execute in the client. The js can do almost anything js is capable of - including stealing the user's cookie details. Now if the user is logged into the affected site, and one gets their cookie data, they have enough information to potentially mimic the user by copying their PHP session id. If you can mimic the user - you can access the application and do "bad things" from their account. Lots more to it, but there one possible usage...
User avatar
andym01480
Forum Contributor
Posts: 390
Joined: Wed Apr 19, 2006 5:01 pm

Post by andym01480 »

Okay. Quickly looked at mod_rewrite in google and also at the article you linked to Maugrim.

If I'm not using mod_rewrite in .htaccess files, is

Code: Select all

$_SERVER[PHP_SELF]
safe from attack?
mudvein
Forum Commoner
Posts: 45
Joined: Wed Mar 16, 2005 4:39 pm

Re: form action="$_SERVER['PHP_SELF']"

Post by mudvein »

seodevhead wrote:Hey guys... I have heard various articles over the past couple months state that you shouldn't rely on $_SERVER type variables as they are unpredictable, etc.

But is it safe to do the following for a form on my website?

Code: Select all

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
Or does this leave me open to a security hole? Can a user impart his will on this PHP_SELF variable I am echoing? Thanks for any advice and suggestions. Take care.
in all reality, if you are posting to the page you are showing, you don't even NEED to put an action statement in there...
so this

Code: Select all

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
would just become this :

Code: Select all

<form method="post">

after trying it out, you will see you get the exact same result...
Post Reply