5

I am using this code below to control pagination. It's using $_SERVER['PHP_SELF'] so I wanted to know if its secure this way or what do I have to do to make $_SERVER['PHP_SELF'] secure?

<?php 

    if($rows > 10) {
        echo '<a id=nex href="'.$_SERVER['PHP_SELF'].'?pg='.($startrow+10).'">
        Next</a>';
    } 

    $prev = $startrow - 10;

    if ($prev >= 0) {
        echo '<a id=pex href="'.$_SERVER['PHP_SELF'].'?pg='.$prev.'">
        Previous</a>';
    }

?>
Colin Brock
  • 21,267
  • 9
  • 46
  • 61
ariel
  • 2,962
  • 7
  • 27
  • 31
  • "*secure*" has many meanings - what's yours? –  Apr 22 '12 at 21:31
  • "secure" meaning $_SERVER['PHP_SELF'] basically executes whats in the address bar. I am new to PHP but i was told that $_SERVER['PHP_SELF'] has to be sanitized... – ariel Apr 22 '12 at 21:32
  • there is no issue in this case, there is when you use $_SERVER['PHP_SELF'] as a form action. And then only if your silly enough to accept any input with out checking it. –  Apr 22 '12 at 21:34
  • 1
    possible duplicate of [PHP_SELF and XSS](http://stackoverflow.com/questions/6080022/php-self-and-xss) – John Conde Apr 22 '12 at 21:36

3 Answers3

10

You should use filter_input: http://php.net/filter_input

$phpSelf = filter_input(INPUT_SERVER, 'PHP_SELF', FILTER_SANITIZE_URL);

Then use $phpSelf instead of the $_SERVER['PHP_SELF'].

This is better than htmlspecialchars, but an ideal solution would be using a tool like http://htmlpurifier.org/

alganet
  • 2,527
  • 13
  • 24
  • Thanks. Since i am new to PHP i am unsure what the difference is in using filter_input vs htmlspecialchars? can you clarify? – ariel Apr 22 '12 at 21:54
  • htmlspecialchars only converts some HTML symbols to entities, but the user can still inject foreign characters or UTF-8 special chars. filter_input with FILTER_SANITIZE_URL validates an URL link (you can also see more sanitizer types on the PHP manual) but this is also incomplete (there are complex XSS techniques that can bypass that). HTMLPurifier is even better because is written to avoid XSS and circumvent all these problems with other functions. – alganet Apr 22 '12 at 22:02
  • ok but htmlspecialchars(); would still work properly for displaying user inputs, right? – ariel Apr 22 '12 at 22:05
9

To prevent XSS attacks, you should use htmlspecialchars() or filter_input() to escape $_SERVER['PHP_SELF']. See this question for more info.

Note also that if you start an href attribute with ? and no path, the browser will append the subsequent query string to the current request, much like a relative link would append to the same directory.

I'm assuming that you're sanitizing $prev and $startrow elsewhere. The mathematical comparisons should make them safe, but if they're coming from $_GET it's a good idea to run them through intval() before you do anything else.

Community
  • 1
  • 1
Austin Smith
  • 146
  • 3
  • Thanks. This is what i have on the top of the query: //New script begin if (!isset($_GET['pg']) or !is_numeric($_GET['pg'])) { $startrow = 0; } else { $startrow = (int)mysql_real_escape_string($_GET['pg']); } So using (int) and escaping is correct? – ariel Apr 22 '12 at 21:55
  • Passing a value through inval() or casting it to an integer with (int) yield the same result, yes. – Austin Smith Apr 22 '12 at 22:16
  • psst: If you want to prevent injection, just remote the action attribute completely. It defaults to an empty string, which is the relative URI that represents what `$_SERVER['PHP_SELF']` has in 99.9% of the cases so ... . – hakre Dec 26 '14 at 16:11
0

$_SERVER['PHP_SELF'] is already secure in a sense that no character can produce alterations to your HTML syntax you want to post. The only thing is the filename itself.

Normally you should use methods like htmlspecialcharsto sanitize output prior to posting it to the browser.