代码之家  ›  专栏  ›  技术社区  ›  sh03

双重转义是不是错了?

  •  3
  • sh03  · 技术社区  · 15 年前

    我有一个数据库类,它在使用mysqli_real_escape_string()构建查询之前自动转义输入字符串。 但可能是在脚本中,字符串被转义,然后传递给数据库类,数据库类再次转义它。那可能是错的吗?会发生什么?

    6 回复  |  直到 15 年前
        1
  •  5
  •   NikiC    13 年前

    在第一次通过时 mysqli_real_escape_string ,通过插入 \ 在每个危险人物面前:

    NUL(ASCII 0)、\n、\r、\、'、“”和Control-Z:

    NUL (chr(0)) becomes "\0" (chr(92).chr(48))
    \n (chr(13)) becomes "\n" (chr(92).chr(110))
    \r (chr(10)) becomes "\r" (chr(92).chr(114))
    \ (chr(92)) becomes "\\" (chr(92).chr(92))
    ' (chr(39)) becomes "\'" (chr(92).chr(39))
    " (chr(34)) becomes "\"" (chr(92).chr(34))
    Control-Z (chr(26)) becomes "\Z" (chr(92).chr(90))
    

    在第二个通道上 mysqli_real_escape_字符串 ,和 \ 再次转义:

    "\0" (chr(92).chr(48)) becomes "\\0" (chr(92).chr(92).chr(48))
    "\n" (chr(92).chr(110)) becomes "\\n" (chr(92).chr(92).chr(110))
    "\r" (chr(92).chr(114)) becomes "\\r" (chr(92).chr(92).chr(114))
    "\\" (chr(92).chr(92)) becomes "\\\\" (chr(92).chr(92).chr(92).chr(92))
    "\'" (chr(92).chr(39)) becomes "\\'" (chr(92).chr(92).chr(39))
    "\"" (chr(92).chr(34)) becomes "\\"" (chr(92).chr(92).chr(34))
    "\Z" (chr(92).chr(90)) becomes "\\Z" (chr(92).chr(92).chr(90))
    

    对字符串进行双重转义不会产生任何漏洞,但会在要保存到数据库中的字符串中插入许多额外的“\”字符。

    逃跑的最好方法是: 1) 关闭魔法引号 2) 只使用带有命名参数的查询,并且在将任何内容传递到查询之前不要转义。MySQL(以及所有其他数据库供应商)将正确地转义字符串。(但是,您可能会遇到chr(0)终止字符串的问题)。

    如果必须使用字符串查询,请在将数据插入查询之前,对其进行一次且仅一次转义。不要转义整个查询。

        2
  •  6
  •   Amber    15 年前

    因为你没有好的方法告诉我 其他 结束(当您从数据库中提取数据时)它被转义了多少次,不一致的双转义字符串将导致在结束数据中转义了以前没有的东西-因为您将添加两层转义,但只有一层转义。

    基本上,你需要有一个常数 水平 逃避的方式——要么总是逃避一次(然后把它们取消一次)要么总是逃避两次(然后把它们取消两次)等等——但决不能混为一谈。

        3
  •  3
  •   Rotsor    15 年前

    双转义字符串没有什么错,只要在使用前保证双转义。

    如果忘记对它进行双重调整,那么用户最终将读取一个转义字符串,这不是很好。

        4
  •  1
  •   Yuliy    15 年前

    除非您对此作出解释,否则双转义字符串的呈现将不正确。您可能看到过一些文本偶尔以转义形式呈现的示例(例如,使用额外的反斜杠或HTML实体)。

        5
  •  1
  •   Sébastien VINCENT    15 年前

    是的,可能是错的,因为你可以 我们走吧 在你的数据库里。

    你在逃避 SQL注入 或查询语法错误,而不是“转换”要存储的数据。如果你想储存 走吧 在数据库中,生成查询时应仅转义一次。您不必“unescape”来自数据库的值。当您查看数据库时,不应该看到带有转义字符的值。

    对于PHP初学者来说,转义是一个真正的问题,这可能是由于magic_quote()函数造成的。你应该看看 http://php.net/manual/en/security.magicquotes.php 你不应该使用那个功能,它很混乱。在脚本中,如果无法修改php.ini以禁用此功能,则可以在运行时使用以下命令执行此操作:

    if (get_magic_quotes_gpc()) {
    $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
    while (list($key, $val) = each($process)) {
        foreach ($val as $k => $v) {
            unset($process[$key][$k]);
            if (is_array($v)) {
                $process[$key][stripslashes($k)] = $v;
                $process[] = &$process[$key][stripslashes($k)];
            } else {
                $process[$key][stripslashes($k)] = stripslashes($v);
            }
        }
    }
    unset($process);
    }
    

    注意这个代码来自 http://www.php.net/manual/en/security.magicquotes.disabling.php

    花点时间正确地理解如何处理转义,将来会节省很多时间。

        6
  •  1
  •   Knubo    15 年前

    对于MySQL,使用准备好的语句,不需要在数据库级别转义字符串。

    对于PHP,记住可以同时使用“和”来构建字符串。这可以用来避免引用字符串。如果你的字符串以“那么你不必引用你的”。

    推荐文章