【问题标题】:Magic quotes in PHPPHP中的魔术引号
【发布时间】:2010-09-18 05:43:57
【问题描述】:

根据PHP manual,为了使代码更便携,他们建议使用类似以下的东西来转义数据:

if (!get_magic_quotes_gpc()) {
    $lastname = addslashes($_POST['lastname']);
} else {
    $lastname = $_POST['lastname'];
}

我将执行其他验证检查,但就转义数据而言,上述内容的安全性如何?我还看到 PHP 6 将弃用魔术引号。这将如何影响上述代码?我宁愿不必依赖特定于数据库的转义函数,如 mysql_real_escape_string()。

【问题讨论】:

    标签: php security magic-quotes


    【解决方案1】:

    魔术引号本身就被破坏了。它们旨在清理对 PHP 脚本的输入,但在不知道如何使用该输入的情况下,不可能正确清理。如果有的话,您最好检查是否启用了魔术引号,然后在 $_GET/$_POST/$_COOKIES/$_REQUEST 上调用 stripslashes(),然后在您在某处使用它的地方清理变量。例如。 urlencode() 如果您在 URL 中使用它,htmlentities() 如果您将其打印回网页,或者如果您将其存储到数据库中,则使用数据库驱动程序的转义函数。请注意,这些输入数组可能包含子数组,因此您可能需要编写一个可以递归到子数组中的函数来去除这些斜线。

    PHPman page on magic quotes 同意:

    “此功能已被弃用为 PHP 5.3.0 和 PHP 删除 5.4.0。强烈建议不要依赖此功能。魔术行情是一个 自动逃逸的进程 PHP 脚本的传入数据。它是 喜欢用魔术引号编码 关闭并转义数据 运行时,根据需要。”

    【讨论】:

    • 只是 PHP6 从未见识过。
    【解决方案2】:

    PDOMysqli 的预处理语句是防止 SQL 注入的更好方法。

    但是,如果您要为每个 SQL 查询迁移基于 Magic Quotes 的遗留代码,您可以参考 yidas/php-magic-quotes 在 PHP 5.4 以上版本的环境中实现 Magic Quotes。

    https://github.com/yidas/php-magic-quotes

    【讨论】:

      【解决方案3】:

      刚刚在PHP manual pages 上找到了这个,看起来是一种非常聪明的剥离 em 的方法(处理键和值...):

      if (get_magic_quotes_gpc())
      {
          $_GET = json_decode(stripslashes(json_encode($_GET, JSON_HEX_APOS)), true);
          $_POST = json_decode(stripslashes(json_encode($_POST, JSON_HEX_APOS)), true);
          $_COOKIE = json_decode(stripslashes(json_encode($_COOKIE, JSON_HEX_APOS)), true);
          $_REQUEST = json_decode(stripslashes(json_encode($_REQUEST, JSON_HEX_APOS)), true);
          ini_set('magic_quotes_gpc', 0);
      }
      

      【讨论】:

      • 我是手册上那个注释的作者,只是不要忘记,因为我们使用的是JSON_HEX_APOS 常量,所以这个解决方案只与 PHP 5.3 及更高版本兼容,请参阅这个问题(stackoverflow.com/questions/2077711/…) 了解更多信息。
      【解决方案4】:

      您的示例代码是向后的,您应该执行以下操作:

      if (get_magic_quotes_gpc()) {
        $lastname = stripslashes($_POST['lastname']);
      } else {
        $lastname = $_POST['lastname'];
      }
      

      请注意,这会使您的输入数据完全按照用户键入的方式保持“原始”状态 - 没有额外的反斜杠,并且可能会加载 SQL 注入和 XSRF 攻击 - 这正是您想要的。然后,请确保您始终使用以下方法之一:

      • echo将变量写入HTML时,将其包装在htmlentities()
      • 将其放入mysql时,使用prepared statements或mysql_real_escape_string()作为最低限度。
      • echo将变量写入Javascritpt代码时,使用json_encode()

      Joel Spolsky 在Making Wrong Code Look Wrong 中有一些很好的入门建议

      【讨论】:

        【解决方案5】:

        对您的代码提出 PHP 5.2 或更高版本的要求并使用filter APIfilter_* 函数直接访问原始输入数据(它们从未接触过$_POST 等),因此它们完全不受magic_quotes_gpc 的影响。

        那么这个例子:

        if (!get_magic_quotes_gpc()) {
            $lastname = addslashes($_POST['lastname']);
        } else {
            $lastname = $_POST['lastname'];
        }
        

        可以变成这样:

        $lastname = filter_input(INPUT_POST, 'lastname');
        

        【讨论】:

          【解决方案6】:

          “我宁愿不必依赖数据库特定的转义函数,如 mysql_real_escape_string()”

          addslashes 也可以被欺骗,看看这篇文章:

          http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

          【讨论】:

            【解决方案7】:

            你可以试试这个:

            if (get_magic_quotes_gpc()) { 
                      $_REQUEST = array_map('stripslashes', $_REQUEST); 
                      $_GET = array_map('stripslashes', $_GET);
                      $_POST = array_map('stripslashes', $_POST);
                      $_GET = array_map('stripslashes', $_COOKIES);
            
                }
            

            【讨论】:

              【解决方案8】:

              魔术引号是一个设计错误。使用它们与保持理智不相容。

              我更喜欢:

              if (get_magic_quotes_gpc()) {
                 throw new Exception("Turn magic quotes off now!");
              }
              

              不要编写代码来兼容固有的损坏设置。而是通过让您的代码FAIL FAST 来保护它们的使用。

              【讨论】:

              • 令人敬畏的快速失败。不知道!
              【解决方案9】:

              “我宁愿不必依赖数据库特定的转义函数,如 mysql_real_escape_string()”

              然后使用PDO 之类的东西。但无论如何,你必须扭转魔术引号造成的伤害。

              【讨论】:

                【解决方案10】:

                关于使用数据库特定的转义函数,您非常需要。我发现只使用addslashes() 在 MySQL 的极少数情况下会失败。您可以编写一个转义函数来确定您使用的是哪个数据库,然后使用适当的转义函数。

                【讨论】:

                  【解决方案11】:

                  我在我的网站头文件中使用以下代码来反转magic_quotes的效果:

                  <?php
                  
                  // Strips slashes recursively only up to 3 levels to prevent attackers from
                  // causing a stack overflow error.
                  function stripslashes_array(&$array, $iterations=0) {
                      if ($iterations < 3) {
                          foreach ($array as $key => $value) {
                              if (is_array($value)) {
                                  stripslashes_array($array[$key], $iterations + 1);
                              } else {
                                  $array[$key] = stripslashes($array[$key]);
                              }
                          }
                      }
                  }
                  
                  if (get_magic_quotes_gpc()) {
                      stripslashes_array($_GET);
                      stripslashes_array($_POST);
                      stripslashes_array($_COOKIE);
                  }
                  
                  ?>
                  

                  然后我可以编写我的其余代码,就好像 magic_quotes 从未存在过一样。

                  【讨论】:

                    【解决方案12】:

                    是的,这不是最好的方法,也不是最安全的。最好根据您要逃避的目的进行逃避。如果要存储在 mysql 数据库中,请使用 mysql_real_escape_string 考虑其他语言环境、字符集。对于 HTML,htmlentities。用于代码,escapeshellcmd,escapeshellarg。是的,如果打开了魔术引号,您可能需要先使用stirpslashes。但最好不要指望它或使用它。

                    【讨论】:

                      猜你喜欢
                      • 2012-05-20
                      • 2011-05-17
                      • 2011-01-08
                      • 2011-02-13
                      • 2012-10-16
                      • 2013-01-23
                      • 2013-12-08
                      • 2013-11-15
                      • 2019-03-12
                      相关资源
                      最近更新 更多