Reputation: 11448
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?
Upvotes: 12
Views: 25347
Reputation: 3764
Update: FILTER_SANITIZE_STRING is deprecated since PHP 8.1, see official PHP documentation: https://www.php.net/manual/en/filter.filters.sanitize.php
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 );
Upvotes: 21
Reputation: 3654
Lets say you are accessing the query params as variables in the PHP 5.x as follows but is prone 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());
}
?>
To prevent XSS from $_SERVER['QUERY_STRING']
,
htmlentities
to read the $_SERVER['QUERY_STRING']
and decode the query string using html_entity_decode
.parse_str
to extract array of key values of query parameters.filter_var_array
with array to sanitize as the first arg and FILTER_SANITIZE_ENCODED
as the second argument.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());
}
?>
Upvotes: 1
Reputation: 1257
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']);
Upvotes: -3
Reputation: 1412
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.
Upvotes: 0
Reputation: 17772
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.
Upvotes: 10