Replacing $_SERVER["PHP_SELF"]

The $_SERVER['PHP_SELF'] value is often used in the action attribute of forms to get the form passed to the same page as it was displayed on processing. This makes it far easier to redisplay the form if there are errors and keeps the processing of the form in the same file as the form itself . The problem is that $_SERVER['PHP_SELF'] is not guaranteed to contain the value that you expect. It can potentially be tampered with and be used to inject code into the web page.

The solution that some people propose is to wrap the $_SERVER['PHP_SELF'] inside an htmlentities() call so as to escape anything that could be misinterpreted as HTML. Since the regular content should never normally contain any characters that would have that problem the call should have no impact on the value unless it has been tampered with in which case it may result in garbage displaying in the page which is a far better alternative to having that garbage actually run as code. Some people might argue that there are legitimate file names that could create the same problem but I would suggest that as you can control the filenames of the pages on your web site that you should easily be able to avoid any that would cause such conflicts.

Now escaping output where data and code are potentially jumbled together is basically a last resort measure that you should only ever use where it is impossible to keep the data and code separate. There is always a remote possibility that someone will find a way to still get the data interpreted as code using something that the escaping routine doesn't touch. In this instance while we need to treat $_SERVER['PHP_SELF'] as data because it can potentially be changed by visitors, it isn't really data in the sense that it can have a variety of different values. For each web page that field should have exactly one value - the name of the file that contains the current page. If we can substitute a value that cannot be tampered with by visitors then we remove the need to escape the value.

There are a number of simple solutions to this. The most obvious one is to simply hard code the filename into the code. Each of our forms that needs to reload the same page then simply has the filename containing the form hard coded into the action attribute and no PHP to assign the value is required. Other alternatives that are even easier to implement are to specify action="" action="#" or action="?" any of which should also automatically reload the same page (provided that you are not using an obsolete <base> tag to override relative addressing.

Another alternative that retains the use of PHP to set the action for the form is to use basename(__FILE__) instead of $_SERVER['PHP_SELF'] in the action field. Provided that the form tag that you are referencing is directly in the file that needs to be loaded to display the page this will work exactly the same but without the possibility of the value being able to be tampered with by visitors. If you have software that allows you to globally change vales across your entire site then simply changing all of the $_SERVER['PHP_SELF'] references to basename(__FILE__) for all references in your main folder will remove the vulnerability from all of those forms. Where basename(__FILE__) doesn't contain the same value as $_SERVER['PHP_SELF'] though is inside of include files where the $_SERVER['PHP_SELF'] still refers to the main page while basename(__FILE__) refers to the include file itself. If you want to use this alternative inside of include files then you need to assign the value to a separate variable in your main page and use that value from within the includes or if the references inside the include files are inside of functions then pass the value as a parameter to the function. For example:

$thisPage = basename(__FILE__);
<form action="<?php echo $thisPage ?>" ...


function displayForm($page) {
<form action="&;t'?php echo $page ?>" ...


This article written by Stephen Chapman, Felgall Pty Ltd.

go to top

FaceBook Follow
Twitter Follow