95

我希望有一个函数表现为 mysql_real_escape_string 而不连接到数据库,因为有时我需要在没有数据库连接的情况下进行干测试。mysql_escape_string 已被弃用,因此是不可取的。我的一些发现:

http://www.gamedev.net/community/forums/topic.asp?topic_id=448909

http://w3schools.invisionzone.com/index.php?showtopic=20064

4

4 回答 4

77

没有数据库连接就不可能安全地转义字符串。mysql_real_escape_string()准备好的语句需要与数据库的连接,以便它们可以使用适当的字符集转义字符串 - 否则仍然可能使用多字节字符进行 SQL 注入攻击。

如果您只是在测试,那么您不妨使用mysql_escape_string()它,它不能 100% 保证免受 SQL 注入攻击,但如果没有数据库连接,就不可能构建任何更安全的东西。

于 2009-07-22T00:53:58.510 回答
69

好吧,根据mysql_real_escape_string函数参考页:“mysql_real_escape_string()调用MySQL的库函数mysql_real_escape_string,它会转义以下字符:\x00、\n、\r、\、'、”和\x1a。”

考虑到这一点,您发布的第二个链接中给出的功能应该完全符合您的需要:

function mres($value)
{
    $search = array("\\",  "\x00", "\n",  "\r",  "'",  '"', "\x1a");
    $replace = array("\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z");

    return str_replace($search, $replace, $value);
}
于 2009-07-22T00:44:11.250 回答
29

与我的其他答案直接相反,即使使用多字节字符,以下功能也可能是安全的。

// replace any non-ascii character with its hex code.
function escape($value) {
    $return = '';
    for($i = 0; $i < strlen($value); ++$i) {
        $char = $value[$i];
        $ord = ord($char);
        if($char !== "'" && $char !== "\"" && $char !== '\\' && $ord >= 32 && $ord <= 126)
            $return .= $char;
        else
            $return .= '\\x' . dechex($ord);
    }
    return $return;
}

我希望比我更有知识的人能告诉我为什么上面的代码不起作用......

于 2009-07-22T04:38:32.630 回答
6

通过进一步的研究,我发现:

http://dev.mysql.com/doc/refman/5.1/en/news-5-1-11.html

安全修复:

在多字节编码处理中发现了一个 SQL 注入安全漏洞。该错误在服务器中,错误地解析了使用 mysql_real_escape_string() C API 函数转义的字符串。

该漏洞是由 Josh Berkus 和 Tom Lane 作为 OSDB 联盟项目间安全协作的一部分发现并报告的。有关 SQL 注入的更多信息,请参见下文。

讨论。在多字节编码处理中发现了一个 SQL 注入安全漏洞。SQL 注入安全漏洞可能包括这样一种情况,即当用户提供要插入数据库的数据时,用户可能会将 SQL 语句注入服务器将执行的数据中。对于这个漏洞,当使用不感知字符集的转义时(例如PHP中的addlashes()),可以绕过一些多字节字符集(例如SJIS、BIG5和GBK)中的转义。因此,诸如addslashes() 之类的函数无法防止SQL 注入攻击。在服务器端解决此问题是不可能的。最好的解决方案是让应用程序使用 mysql_real_escape_string() 等函数提供的字符集感知转义。

但是,在 MySQL 服务器如何解析 mysql_real_escape_string() 的输出时检测到一个错误。结果,即使使用了字符集感知函数 mysql_real_escape_string(),SQL 注入也是可能的。此错误已修复。

变通方法。如果您无法将 MySQL 升级到包含修复 mysql_real_escape_string() 解析中的错误的版本,但运行 MySQL 5.0.1 或更高版本,则可以使用 NO_BACKSLASH_ESCAPES SQL 模式作为解决方法。(此模式在 MySQL 5.0.1 中引入。) NO_BACKSLASH_ESCAPES 启用 SQL 标准兼容模式,其中反斜杠不被视为特殊字符。结果将是查询将失败。

要为当前连接设置此模式,请输入以下 SQL 语句:

SET sql_mode='NO_BACKSLASH_ESCAPES';

您还可以为所有客户端全局设置模式:

SET GLOBAL sql_mode='NO_BACKSLASH_ESCAPES';

此 SQL 模式也可以在服务器启动时自动启用,方法是使用命令行选项 --sql-mode=NO_BACKSLASH_ESCAPES 或在服务器选项文件中设置 sql-mode=NO_BACKSLASH_ESCAPES(例如,my.cnf 或 my.ini ,取决于您的系统)。(错误#8378,CVE-2006-2753)

另见错误#8303。

于 2009-07-25T07:48:34.800 回答