mysql - 哪些字符实际上能够导致 MySQL 中的 SQL 注入(inject)?

标签 mysql security escaping sql-injection

我们都知道我们应该使用准备好的语句或适当的替换/格式化规则来防止我们的应用程序中的 sql 注入(inject)。

但是,当查看 MySQL 的字 rune 字列表时,我注意到它包含以下字符:

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

现在,虽然 %_ 字符需要转义,以防止将不需要的通配符注入(inject) LIKE 语句,而 '(单引号)、\(反斜杠)和 "(双引号)都需要转义以防止注入(inject)任意 SQL - 可以有任何这些未转义的其他字符直接导致 SQL 注入(inject)漏洞,否则不会存在?有没有人有任何此类漏洞利用的真实示例?

假设我们正在构建我们的查询:

SELECT * FROM users WHERE username='$user'

$user 是否有任何值,其中唯一未转义的字 rune 字是 \b(退格键)、\0( NUL)、\n(换行)、\r(换行)、\t(制表符)或 \Z (Ctrl+Z) 允许将任意 SQL 注入(inject)此查询?

最佳答案

考虑 mysql_real_escape_string() 中的以下行手册:

MySQL requires only that backslash and the quote character used to quote the string in the query be escaped. mysql_real_escape_string() quotes the other characters to make them easier to read in log files.

MySQL 中的 SQL 注入(inject)不应该单独使用这些特殊字符:\b \0 \n \r \t \Z .

然而,字符串文字手册指出以下但指定(或不指定)的原因与 SQL 注入(inject)无关:

If you want to insert binary data into a string column (such as a BLOB column), you should represent certain characters by escape sequences. Backslash (“\”) and the quote character used to quote the string must be escaped. In certain client environments, it may also be necessary to escape NUL or Control+Z. The mysql client truncates quoted strings containing NUL characters if they are not escaped, and Control+Z may be taken for END-OF-FILE on Windows if not escaped.

此外,在一个简单的测试中,不管上面列出的特殊字符是否被转义,MySQL 产生了相同的结果。换句话说,MySQL 甚至不介意:

$query_sql = "SELECT * FROM `user` WHERE user = '$user'";

对于上面列出的字符的非转义和转义版本,上述查询的工作方式类似,如下所示:

$user = chr(8);     // Back Space
$user = chr(0);     // Null char
$user = chr(13);    // Carriage Return
$user = chr(9);     // Horizontal Tab
$user = chr(26);    // Substitute
$user = chr(92) .chr(8);    // Escaped Back Space
$user = chr(92) .chr(0);    // Escaped Null char
$user = chr(92) .chr(13);   // Escaped Carriage Return
$user = chr(92) .chr(9);    // Escaped Horizontal Tab
$user = chr(92) .chr(26);   // Escaped Substitute

简单测试中使用的测试表和数据:

-- Table Structure

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` varchar(10) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

-- Table Data

INSERT INTO `user` ( `user` ) VALUES
( char( '8' ) ),
( char( '0' ) ),
( char( '10' ) ),
( char( '13' ) ),
( char( '9' ) ),
( char( '26' ) );

关于mysql - 哪些字符实际上能够导致 MySQL 中的 SQL 注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14370670/

相关文章:

jquery - 安全、可靠、正确的服务器端密码验证响应应该是什么?

c# - 正则表达式转义问号和双引号

MySQL 数据库规范化、关系和外键的最佳方法

php - 检查哪些用户在线

php - Codeigniter 和 doctrine 连接三个表

security - Symfony2 http_basic 安全性拒绝有效凭据

mysql - 如何按年计算两个字段

c# - 带试用期的 PayPal 定期付款

javascript - 在数据属性 JSON 对象中转义引号和 html

php - 为什么这行代码不需要转义引号