大家都知道,我们应该使用准备好的语句或适当的替换/格式化规则,以防止在应用程序中注入(inject)sql。
但是,在查看MySQL的字符文字列表时,我注意到它包含以下字符:
\0
ASCII NUL(0x00
)字符。 \'
单引号('
)字符。 \"
双引号("
)字符。 \b
退格字符。 \n
换行符(换行符)。 \r
回车符。 \t
制表符。 \Z
ASCII 26(Ctrl + Z)。请参阅表格后面的注释。 \\
反斜杠(\
)字符。 \%
%
字符。 \_
_
字符。 现在,虽然
%
和_
字符需要转义以防止在LIKE语句中注入(inject)不需要的通配符,但是'
(单引号),\
(反斜杠)和"
(双引号)都需要转义。为了防止注入(inject)任意SQL-是否可以将任何其他这些字符转义而直接导致SQL注入(inject)漏洞,否则该漏洞将不存在?有人在现实世界中有这种利用的例子吗?假设我们正在构建如下查询:
SELECT * FROM users WHERE username='$user'
$user
是否有任何值,其中唯一未转义的字符文字是\b
(退格键),\0
(NUL),\n
(换行符),\r
(换行符),\t
(制表符)或\Z
(Ctrl + Z)任意SQL进入此查询? 最佳答案
考虑mysql_real_escape_string()手册中的以下几行:
单独使用这些特殊字符,就不可能在MySQL中进行SQL注入(inject):\b
\0
\n
\r
\t
\Z
。
但是String Literals手册指出了以下内容,但指定的原因(是否指定)与SQL注入(inject)无关:
此外,在一个简单的测试中,无论天气如何,上面列出的特殊字符都已转义或不转义,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' ) );