大家都知道,我们应该使用准备好的语句或适当的替换/格式化规则,以防止在应用程序中注入(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' ) );
    

    09-25 17:24
    查看更多