【问题标题】:What does mysql_real_escape_string() do that addslashes() doesn't?什么是 mysql_real_escape_string() 而addslashes() 没有?
【发布时间】:2010-10-06 18:59:52
【问题描述】:

为什么我们需要一个特定于数据库的函数,比如 mysql_real_escape_string()? addlashes() 不能做什么?

暂时忽略参数化查询的优越替代方案,仅使用 addlashes() 的 web 应用仍然容易受到 SQL 注入的攻击,如果是,如何?

【问题讨论】:

    标签: php security sql-injection


    【解决方案1】:

    在处理多字节编码字符串时,Addslashes 通常不够好。

    【讨论】:

    • 任何以 0x5c 结尾的有效多字节字符的编码都可以在 addslashes() 后面加上引号。 Chris Shiflett 在他的博客上使用 GBK 提供了一个很好的例子。 shiflett.org/blog/2006/jan/…
    • 恰恰相反——一般来说,addlashes 是可以的,但在极少数情况下,我们实际上需要 mres。
    【解决方案2】:

    它添加斜线到:

    \x00, \n, \r, \, ', " and \x1a. characters.
    

    其中addslashes 只添加斜线

    ' \ and NUL
    

    Ilias article 的功能也很详细

    【讨论】:

      【解决方案3】:

      gs 被严厉否决的答案实际上是正确的。

      标准 SQL 使用加倍来转义文字撇号。 MySQL 使用非标准反斜杠进行转义是默认设置,但它可以被禁用,而且经常被禁用,特别是在 sql_mode ANSI 中。

      在这种情况下,只有双倍语法有效,并且您使用的任何应用程序都使用了 addlashes(或其他临时转义方法)将中断。 mysql_real_escape_string 将使用最适合连接的 sql_mode 的任何转义方法。

      如果您仍在使用那些重复使用较低 128 个字符的讨厌的东亚编码,那么多字节编码问题也很重要,但您确实想改用 UTF-8。另一方面,\n-转义无关紧要,因为 MySQL 可以完美地处理语句中的原始换行符。

      【讨论】:

        【解决方案4】:

        mysql_real_escape_stringaddslashes 做得更多

        addslashes 在纯 ascii 上运行,对数据库一无所知。它逃脱了:

        • '\'
        • "\"
        • \\\
        • ASCII 0\0

        mysql_real_escape_string 的目的是“创建一个可以在 SQL 语句中使用的合法 SQL 字符串”。 mysql_real_escape_string 考虑到连接的当前字符集(这就是为什么你必须始终传递一个有效的 $mysql 对象)。

        它执行以下操作(取自 MySQL C API 文档):

        • 以不会引起问题的方式编码:\'"、ASCII 0\n\rControl+Z
        • 确保0 字节终止字符串(在 C api 中)
        • 如果 $mysql 中链接的 DB 使用宽字符集,则可以执行多字节 (ascii) 到宽字符的转换。

        我真的不知道 PHP 如何在内部存储字符串,但关键是当您使用 mysql_real_escape_string 时,所有这些都对 PHP 可用。我想主要区别在于mysql_real_escape_string 考虑连接的字符集,而addslashes 不能(它甚至不知道您连接到什么数据库)。

        【讨论】:

        【解决方案5】:

        somedb_real_escape_string() 是特定于数据库的,addslashes() 不是。

        对于 MySQL,这意味着:

        mysql_real_escape_string() 调用 MySQL的库函数 mysql_real_escape_string,其中 将反斜杠添加到以下内容 字符:\x00、\n、\r、\、'、" 和 \x1a.

        (来自手册。)

        【讨论】:

          【解决方案6】:

          为什么我们需要像 mysql_real_escape_string() 这样的特定于数据库的函数?

          实际上,大多数时候我们不会。
          一些极其罕见的编码需要此功能,并稍微美化 mysql 日志和转储。

          仅使用 addlashes() 的 web 应用是否仍然容易受到 SQL 注入的攻击?

          只要它使用任何单字节字符集或 utf8 - addslashes() 绝对安全。

          addslashes() 不能做什么?

          它可以保护 SQL 字符串字面量,以防一些罕见的编码。

          但是,它不能自己完成。必须首先使用mysql_set_charset() 函数设置正确的编码。如果未使用此函数,mysql_real_escape_string() 在字符集处理方面的行为与addslashes() 完全相同 - 根本没有区别

          【讨论】:

          • 只要它使用任何单字节字符集或 utf8 - 使用 addlashes() 是完全安全的。为什么你会使用addslashes 作为一种做法,而一旦你使用 Unicode,就突然不得不改变你的做法?
          • 不幸的是,从 PHP 你必须set the character set at the server level or use mysqli_set_charset。 C 中的情况并非如此。
          • @bobobobo “[addslashes 对 utf8 来说是完全安全的……如果你在使用 Unicode 后突然不得不改变你的做法,为什么还要使用 addslashes?”你误会了; UTF-8 Unicode。唯一易受攻击的情况是 non-Unicode 字符集,例如 GBK。也就是说,对于任何使用 Unicode 的人来说,addslashes() 都是完全安全的,而只有那些选择使用奇怪的国家字符集代替 Unicode 的人才不安全。
          • 客观地解决addslashes() 案例的极其罕见答案之一。普通常识!
          【解决方案7】:

          我知道的唯一真正的区别是 mysql_real_escape_string() 在转义输入字符串时会考虑数据库的字符集。这两个函数都不会转义通配符 % 和 _,这仍然会使脚本对某些 SQL 注入开放。

          【讨论】:

          • %和_与SQL注入无关。
          • 在 MySQL 中,% 可以用作 GRANT 语句中的通配符。 MySQL 还将 _ 视为语句中的单个字符通配符。
          • %和_与SQL注入无关。
          【解决方案8】:

          根据PHP manual

          mysql_real_escape_string() 调用 MySQL 的库函数 mysql_real_escape_string,该函数在以下字符前添加反斜杠:\x00、\n、\r、\、'、" 和 \x1a。

          【讨论】:

            【解决方案9】:

            PHP 的 mysql_real_escape_string 函数或多或少会询问 mysql 哪些字符需要转义,其中的addslashses 函数只会在前面添加一个反斜杠和任何单引号 (') 、双引号 (")、反斜杠 () 或 NUL(NULL 字节)字符。

            这两个实际效果是,addslashes 往往不适用于多字节字符,更重要的是,通过询问 mysql 需要转义哪些字符,可以避免未来可能的兼容性。使用 assslashes 有点像将几个特定字符硬编码到转义序列中。

            【讨论】:

              【解决方案10】:

              它应该以其他引用工具没有的方式为 MySQL 转义字符串。

              然而,更可取的是使用 mysqli 接口,并使用参数化的准备查询,而不是尝试确保所有字符串都正确转义。使用参数化查询避免了对这种混乱的字符串工作的需要,并大大降低了 SQL 注入的风险。

              编辑:我将澄清一下为什么我考虑引用一个坏主意:很容易忘记何时何地需要引用 - 无论您的变量是字符串还是数字,是否已经被引用,等等。参数化查询没有这些问题,并且完全不需要引用。

              【讨论】:

              • 我想我应该澄清一下,我非常清楚参数化查询的优越性:)
              【解决方案11】:

              根据我的理解 mysql_real_escape_string() 更精确地完成工作,因为它与 db 通信以首先检查需要编码的内容,然后进行相应的编码,不是吗?因此,它可以更有效地工作

              为什么你想先做addslashes然后你会在显示数据之前删除那个slashes并且仍然addslashes不如mysql_real_escape_string高效,如果你使用mysql_query之类的db函数进行查询,请使用mysql_real_escape_string,或者我认为PDO与prepare是更好的方法,因为 mysql_real_escape_string 是特定于数据库的

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-04-17
                • 2015-06-13
                • 2012-02-29
                相关资源
                最近更新 更多