简体   繁体   中英

Sanitize query string in PHP

I have a webpage with a query string.

In PHP I have:

$querystring=$_SERVER["QUERY_STRING"];
echo "<html><head></head><body>
<a href='index.php?$querystring'>test</a>
</body></html>";

Do I need to sanitize the querystring?
If yes, how do I sanitize and what are some possible attacks if I don't?

If you're running PHP >= 5.2.0, use filter_input or filter_input_array .

Let's say your URL and query string is something like http://example.com/?liquor=gin&mixer=tonic&garnish=lime .

To filter, you would do something like the following.

/*
 FILTER_SANITIZE_STRING removes most dangerous characters. That may 
 not always be what you want. Read the PHP filters docs. 

 We are also overwriting the $_GET array (the query string) with the sanitized
 versions of these variables.
*/

$_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);

/* 
rebuild query string using white listed variables, 
not $_GET to prevent variable injection as Mārtiņš Briedis 
suggests above.
*/

$qv['liquor']  = $_GET['liquor'];
$qv['mixer']   = $_GET['mixer'];
$qv['garnish'] = $_GET['garnish'];

# build and URL encode the query string using the above array.
$querystring = http_build_query( $qv );

You should use htmlspecialchars($query, ENT_QUOTES) to prevent any XSS attacks.

echo "<html><head></head><body>
<a href='index.php?".htmlspecialchars($querystring, ENT_QUOTES)."'>test</a>
</body></html>"

But still, you should white list any parameters, because a smart attacker could forge a query and attempt a CSRF attack.

Lets say you are accessing the query params as variables in the PHP 5.x as follows but is prone to XSS

Vulnerable to XSS

<?php
// http://example.com/mypage.php?a=hi&b=wow&c=<script type='text/javascript'>alert('XSS Attacked!');</script>

try{
    $q = $_SERVER['QUERY_STRING'];
    parse_str( $q, $arr );
    extract($arr);
    echo '<pre>';
    echo 'a is = ' . $a;
    echo PHP_EOL;
    echo 'b is = ' . $b;
    echo PHP_EOL;
    echo 'c is = ' . $c;
    echo '</pre>';

}
catch(Exception $e){
    error_log($e->getMessage());
}


?>

Prevent XSS from $_SERVER['QUERY_STRING']

To prevent XSS from $_SERVER['QUERY_STRING'] ,

  • Use htmlentities to read the $_SERVER['QUERY_STRING'] and decode the query string using html_entity_decode .
  • Use parse_str to extract array of key values of query parameters.
  • Filter and Sanitize the array using filter_var_array with array to sanitize as the first arg and FILTER_SANITIZE_ENCODED as the second argument.
  • Use extract to make keys php variables with respective values.
<?php
// http://example.com/mypage.php?a=hi&b=wow&c=<script type='text/javascript'>alert('XSS Attacked!');</script>
try{
    $q = htmlentities($_SERVER['QUERY_STRING']);
    parse_str( html_entity_decode($q), $arr );
    $arr=filter_var_array($arr, FILTER_SANITIZE_ENCODED);
    extract($arr);
    echo '<pre>';
    echo 'a is = ' . $a;
    echo PHP_EOL;
    echo 'b is = ' .  $b;
    echo PHP_EOL;
    echo 'c is = ' .  $c;
    echo '</pre>';

}
catch(Exception $e){
    error_log($e->getMessage());
}

?>

In this case you should use urlencode function.

htmlspecialchars/htmlentities are more appropriate when you are going to output value of the query param at the link's title for example, but no at the href/src attributes.

You can sanitize the query using several ways, but that is not the place to do that. Even if you send a safe query by GET, someone can change the query on the address bar or using tamper data. You have to sanitize on index.php (or wherever you process the data). If you are using MySQL, you have to sanitize this way:

$field = mysql_real_scape($_GET['field']);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM