PHP / MYSQL:消除用户输入 - 这是一个坏主意吗?

时间:2009-11-28 06:43:42

标签: php mysql sanitization

我有一个“go”脚本可以获取所请求的任何其他脚本,这是我写的用于清理用户输入的内容:

foreach ($_REQUEST as $key => $value){
    if (get_magic_quotes_gpc()) 
    $_REQUEST[$key] = mysql_real_escape_string(stripslashes($value));  
    else
    $_REQUEST[$key] = mysql_real_escape_string($value); 
}

我还没有看到其他人使用这种方法。有什么理由不去吗?

编辑 - 修改为适用于数组:

function mysql_escape($thing) {
  if (is_array($thing)) {
    $escaped = array();
    foreach ($thing as $key => $value) {
      $escaped[$key] = mysql_escape($value);
    }          
    return $escaped;
  }
  // else
  if (get_magic_quotes_gpc()) $thing = stripslashes($thing);
  return mysql_real_escape_string($thing);
}

foreach ($_REQUEST as $key => $value){
    $_REQUEST[$key] = mysql_escape($value); 
}

5 个答案:

答案 0 :(得分:9)

我发现在使用数据时逃避数据要好得多,而不是在路上。您可能希望在JSON,XML,Shell,MySQL,Curl或HTML中使用这些数据,并且每个数据都有它自己的方式逃避数据。


让我们快速回顾一下为什么在不同情况下需要逃避:

如果您使用引号分隔字符串,则需要能够转义引号。 如果您使用的是xml,则需要将“内容”与“标记”分开 如果您使用的是SQL,则需要将“命令”与“数据”分开 如果您在命令行中,则需要将“命令”与“数据”分开

这一般是计算的一个基本方面。因为分隔数据的语法可以在数据中出现,所以需要有一种方法来区分DATA和SYNTAX,从而逃避。

在网络编程中,常见的逃避案例是: 1.将文本输出为HTML 2.将数据输出到HTML属性 3.将HTML输出为HTML 4.将数据插入Javascript 5.将数据插入SQL 6.将数据插入shell命令

如果处理不当,每个人都会有不同的安全隐患。这真的很重要!让我们在PHP的背景下回顾一下:

  1. 将文字转换为HTML: 用htmlspecialchars(...)

  2. 数据到HTML属性 htmlspecialchars(...,ENT_QUOTES)

  3. HTML转换为HTML 使用HTMLPurifier等库来确保只存在有效标记。

  4. 将数据导入Javascript 我更喜欢json_encode。如果要将其放在属性中,则仍需要使用#2,例如

  5. 将数据插入SQL 每个驱动程序都有某种类型的escape()函数。这是最好的。如果您使用普通的latin1字符集运行,则addslashes(...)是合适的。不要忘记引号AROUND addslashes()调用:

    “INSERT INTO table1 SET field1 ='”。 addslashes($ data)。 “'”

  6. 命令行上的数据 escapeshellarg()和escapeshellcmd() - 阅读手册

  7. - 牢记这些,您将消除95%*的常见网络安全风险! (*猜测)

答案 1 :(得分:3)

如果您的$_REQUEST中有数组,则其值不会被清理。

答案 2 :(得分:3)

我已经制作并使用了这个:

<?php
function _clean($var){
    $pattern = array("/0x27/","/%0a/","/%0A/","/%0d/","/%0D/","/0x3a/",
                     "/union/i","/concat/i","/delete/i","/truncate/i","/alter/i","/information_schema/i",
                     "/unhex/i","/load_file/i","/outfile/i","/0xbf27/");
    $value = addslashes(preg_replace($pattern, "", $var));
    return $value;
}

if(isset($_GET)){
    foreach($_GET as $k => $v){
        $_GET[$k] = _clean($v);
    }
}

if(isset($_POST)){
    foreach($_POST as $k => $v){
        $_POST[$k] = _clean($v);
    }
}
?>

答案 3 :(得分:2)

您的方法会尝试清理所有请求数据以插入数据库,但是如果您只是想输出它呢?输出中会有不必要的反斜杠。此外,无论如何,转义不是防止SQL异常的好策略。通过使用参数化查询(例如在PDO或MySQLi中),您将“转义”问题“传递”到抽象层。

答案 4 :(得分:2)

除了没有递归到数组和不必要的转换,例如整数之外,这种方法在清理之前编码用于SQL语句的数据。 mysql_real_escape_string()逃避数据,它没有消毒它 - 逃避和消毒不是一回事。

清理是许多PHP脚本在使用之前仔细检查输入数据的可接受性的任务。我认为对未转义的数据做得更好。在进入SQL之前,我通常不会转义数据。那些喜欢使用Prepared Statements的人会这样做。

还有一件事:如果输入数据可以包含utf8字符串,那么它们似乎应该在转义之前进行验证。我经常在清理之前在$ _POST上使用递归的utf8清理器。