Exploiting PHP SELF

Eric Butera emailed me with a very interesting topic about protecting against PHP_SELF exploits. I thought it might be a good idea to gather a few test cases demonstrating the problem. Why PHP allows these URL’s is beyond me and it wouldn’t take much work to filter out these malicious URL’s in the PHP code.

For any of you that don’t know, it’s possible to inject code into PHP_SELF. It works by supplying a “/” after the actual PHP file then entering your desired code. I’ve done 4 test cases which show how it’s possible to inject javascript and perform a redirect on code which doesn’t filter PHP_SELF correctly.

Test case 1

Injects data into a HTTP header, although this scenario is not very likely I thought I would include it to show that even running htmlentities or htmlspecialchars won’t save you from attack completely.

Test case 2

Shows how easy it is to inject XSS into links, this is very likely as many PHP applications ofter refer to the same page to change the current action/display.

Test case 3

A search page often includes references to PHP_SELF and can be exploited as easily as links.

Test case 4

Finally I show how code can be injected directly on the page without the need to break out of anything.

The test cases can be downloaded here:-
Test cases

17 Responses to “Exploiting PHP SELF”

  1. Francesc Rosàs writes:

    I think all these are cases of XSS bugs. Escape the content correctly and you won’t have any problem. On the other side, I prefer to use REQUEST_URI as it also works with “user-friendly” (mod_rewrited) URLs.

    <?php echo htmlspecialchars($_SERVER['REQUEST_URI']) ?>

  2. Gareth Heyes writes:

    @Francesc

    Yep that’s why I provided the test cases so that developers are aware that they should escape the data correctly. 2-4 are XSS issues and test case 1 deals with http header injection and redirection.

  3. Sean Coates writes:

    I blogged about this 2.5 years ago, here: http://blog.phpdoc.info/archives/13-XSS-Woes.html

    (-:

    S

  4. Gareth Heyes writes:

    @Sean

    Yeah that’s pretty bad, I know it isn’t new but a reader asked me the question so it can’t do any harm bringing the subject up again.

  5. Eric Butera writes:

    @Francesc:
    You need to use ENT_QUOTES as the second parameter just in case because by default ‘ will not be encoded.

    @Gareth:
    Thank you for the time for this post! Hopefully now this will be enough to convince the powers that be to fix this stuff.

  6. Francesc Rosàs writes:

    @Eric:
    I didn’t know it. Thanks! Luckily I don’t use single quotes at HTML level.

    Anyway I’m gonna change my HTML escaping function to this:

    function eh ($string)
    {
    echo htmlspecialchars($string, ENT_QUOTES);
    }

    Being so essential, I don’t understand why PHP doesn’t have something like this built in.

  7. Stefan Esser writes:

    @Eric:
    There is noone to convince to fix this stuff. PHP_SELF is filled by the webserver. Apache supports PATH_INFO therefore this kind of path ends up in PHP_SELF.

    This problem is known for ages and still many sites are vulnerable to this…

    And well there is always the possibility to just install the Suhosin Extension and you are automatically secure from this kind of XSS.

  8. Guillaume Rossolini writes:

    Hi,
    You might want to escape the variable in header() by calling either urlencode(), and that should be enough. Please remember that each output medium has its proper escaping mechanism. The injection there happens mostly because you don’t escape the output.
    Regards,

  9. Diego writes:

    the test 1 fails on PHP 5.2.4 without any special extension, etc
    The error I get is “Warning: Header may not contain more than a single header, new line detected. in /var/www/htdocs/php_self.php on line 4″
    The other 3 tests do work as expected.

  10. bipin writes:

    <form method=POST action=”<?php echo $PHP_SELF;’SelectedState=$SelectedState’ ?>” >

    in the above line i am trying to pass a variables value onto the same page but its not working can anyone suggest me the syntax

  11. Busby SEO Challenge writes:

    If you want to past variable on the same page you need to pass it by using GET statement.

  12. nuntius writes:

    Bipin, Busby is wrong, apparently he doesn’t understand what this page is about… this is how you do it. Note however, that as this page is describing, this can be exploited.

    <form method=”post” action=”<?php echo $_SERVER['PHP_SELF']; ?>”>
    <!– My Form –>
    </form>

    Check out this page also:
    http://www.gfx-depot.com/forum/-php-server-php-self-validation-t-1636.html

  13. j squid writes:

    Um… have people never heard of local/relative urls????

    saying <a href=’<?php echo $_SERVER[PHP_SELF]?>/cow/lame.php’>link</a> is a retarded waste of time.

    try <a href=’cow/lame.php’ >link</a> or for a form action, action=”…. not ‘action=’<?php blah blah self?>
    it’s such a waste of time.

  14. Jszym writes:

    @j squid, local/relative urls are fine and dandy however is not always a possible solutions. Certain senarios simply require a full path.

    Let’s say for example that I want to redirect ppl to the former page so you need to pass the current page to the next. PHP_SELF is very useful. Just escape and validate properly and you’ll be fine.

  15. dry_gin writes:

    What kind of harm this could possibly (but realistically) do, except for displaying some modified html to the “hacker” HIMSELF (only) ?
    i mean i don’t see a way to alternate php code itself or displaying some useful info like database structure or php source code using this exploit…
    please explain!

  16. dry_gin writes:

    I mean you could probably spam in emails a crafted link to legitimate web site, where at the end of file name it will send user cookies for example to some web-based email sender.
    so the link will look ok in spammer’s email, and so users will probably click on it…
    ok, i guess it make sense to validate php_self after all…

  17. Ruggie writes:

    Use SCRIPT_NAME instead of PHP_SELF