【问题标题】:What characters have to be escaped to prevent (My)SQL injections?必须转义哪些字符以防止(My)SQL 注入?
【发布时间】:2010-11-08 09:14:50
【问题描述】:

我正在使用 MySQL API 的函数

mysql_real_escape_string()

根据文档,它转义了以下字符:

\0
\n
\r
\
'
"
\Z

现在,我查看了 OWASP.org 的 ESAPI 安全库,在 Python 端口中它有以下代码 (http://code.google.com/p/owasp-esapi-python/source/browse/esapi/codecs/mysql.py):

        """
        Encodes a character for MySQL.
        """
        lookup = {
        0x00 : "\\0",
        0x08 : "\\b",
        0x09 : "\\t",
        0x0a : "\\n",
        0x0d : "\\r",
        0x1a : "\\Z",
        0x22 : '\\"',
        0x25 : "\\%",
        0x27 : "\\'",
        0x5c : "\\\\",
        0x5f : "\\_",
        }

现在,我想知道是否真的需要转义所有这些字符。我明白为什么 % 和 _ 在那里,它们是 LIKE 运算符中的元字符,但我不能简单地理解它们为什么要添加退格和制表符(\b \t)?如果您进行查询是否存在安全问题:

SELECT a FROM b WHERE c = '...user input ...';

用户输入在哪里包含制表符或退格字符?

我的问题在这里:为什么他们在 ESAPI 安全库中包含 \b \t?是否有任何情况您可能需要转义这些字符?

【问题讨论】:

标签: mysql security escaping character


【解决方案1】:

关于退格字符的猜测:想象一下,我给你发了一封电子邮件“嗨,这是根据你的需要更新数据库的查询”和一个附加的文本文件

INSERT INTO students VALUES ("Bobby Tables",12,"abc",3.6);

你 cat 文件,看看没问题,然后将文件通过管道传输到 MySQL。然而,你不知道的是,我放了

DROP TABLE students;\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b

在您没有看到的 INSERT STATEMENT 之前,因为在控制台输出上,退格键覆盖了它。呸!

不过,只是猜测。

编辑(无法抗拒):

【讨论】:

  • 感谢 Stefano,它满足了 CC 许可的归属条款。
【解决方案2】:

MySQL manual page for strings 说:

  • \0   一个 ASCII NUL (0x00) 字符。
  • \'   单引号(“'”)字符。
  • \"   双引号(“"”)字符。
  • \b   退格字符。
  • \n   换行符(换行符)。
  • \r   一个回车符。
  • \t   制表符。
  • \Z   ASCII 26 (Control-Z)。请参阅表格后面的注释。
  • \\   反斜杠(“\”)字符。
  • \%   一个“%”字符。请参阅表格后面的注释。
  • \_   一个“_”字符。请参阅表格后面的注释。

【讨论】:

  • 链接死了。考虑更新。
  • 这并没有回答它问“为什么?”的部分问题
  • 请记住,您可能不想总是转义 %_,因为除非在过滤器/搜索上下文中使用反斜杠,否则将按字面意思传递,例如当使用=% 使用like 时,\% 看起来像字符串\%
【解决方案3】:

如果您有任何其他选择,黑名单(识别不良字符)绝不是可行的方法。

您需要结合使用白名单,更重要的是,绑定参数方法。

虽然这个特定的答案侧重于 PHP,但它仍然有很大帮助,并且有助于解释在许多情况下仅通过 char 过滤器运行字符串是行不通的。请看Do htmlspecialchars and mysql_real_escape_string keep my PHP code safe from injection?

【讨论】:

    【解决方案4】:

    用户输入在哪里包含制表符或退格字符?

    一个非常了不起的事实是,迄今为止,大多数用户确实认为必须对用户输入进行转义,并且这种转义“防止注入”。 p>

    【讨论】:

      【解决方案5】:

      Java 解决方案:

      public static String filter( String s ) {
          StringBuffer buffer = new StringBuffer();
          int i;
      
          for( byte b : s.getBytes() ) {
              i = (int) b;
      
              switch( i ) {
                  case  9 : buffer.append( "    " ); break;
                  case 10 : buffer.append( "\\n"  ); break;
                  case 13 : buffer.append( "\\r"  ); break;
                  case 34 : buffer.append( "\\\"" ); break;
                  case 39 : buffer.append( "\\'"  ); break;
                  case 92 : buffer.append( "\\"   );
      
                  if( i > 31 && i < 127 ) buffer.append( new String( new byte[] { b } ) );
              }
          }
      
          return buffer.toString();
      }
      

      【讨论】:

        【解决方案6】:

        不能从用户输入中删除单引号吗?

        例如:$input =~ s/\'|\"//g;

        【讨论】:

        • 如果你想存储一个名字,比如 O'Leary,你会弄乱这个人的名字。如果您要存储像"Help!", David yelled. 这样的句子,则需要保留双引号。所以是的,在某些情况下转储特殊字符可能很好,但不是全部。
        猜你喜欢
        • 2010-12-21
        • 2015-07-22
        • 2011-09-26
        • 1970-01-01
        • 2011-01-20
        • 2010-10-06
        • 1970-01-01
        • 2020-11-12
        相关资源
        最近更新 更多