在PHP中清理查询字符串

时间:2011-12-02 20:09:06

标签: php

我有一个带有查询字符串的网页。

在PHP中我有:

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

我是否需要清理查询字符串?
如果是的话,如果不这样做,我该如何消毒以及可能的攻击是什么?

5 个答案:

答案 0 :(得分:13)

如果您运行的是PHP&gt; = 5.2.0,请使用filter_inputfilter_input_array

假设您的网址和查询字符串类似于http://example.com/?liquor=gin&mixer=tonic&garnish=lime

要进行过滤,您可以执行以下操作。

/*
 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 );

答案 1 :(得分:7)

您应该使用htmlspecialchars($query, ENT_QUOTES)来阻止任何XSS攻击。

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

但是,您仍然应该列出任何参数,因为智能攻击者可以伪造查询并尝试CSRF攻击。

答案 2 :(得分:0)

在这种情况下,您应该使用urlencode函数。

例如,当您要在链接的标题处输出查询参数的值时,htmlspecialchars / htmlentities更合适,但在href / src属性中没有。

答案 3 :(得分:0)

假设您在 PHP 5.x 中将查询参数作为变量访问,如下所示,但容易出现 XSS

易受 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());
}


?>

防止来自 $_SERVER['QUERY_STRING'] 的 XSS

为了防止来自 $_SERVER['QUERY_STRING'] 的 XSS,

  • 使用 htmlentities 读取 $_SERVER['QUERY_STRING'] 并使用 html_entity_decode 解码查询字符串。
  • 使用 parse_str 提取查询参数的键值数组。
  • 使用 filter_var_array 过滤和清理数组,将要清理的数组作为第一个参数,将 FILTER_SANITIZE_ENCODED 作为第二个参数。
  • 使用 extract 使键 php 变量具有各自的值。
<?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());
}

?>

答案 4 :(得分:-3)

您可以使用多种方法清理查询,但这不是那样做的地方。即使您通过GET发送安全查询,也可以更改地址栏上的查询或使用篡改数据。您必须清理index.php(或处理数据的任何位置)。如果您使用的是MySQL,则必须以这种方式进行消毒:

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