【问题标题】:Alternative to mysql_real_escape_string without connecting to DB在不连接数据库的情况下替代 mysql_real_escape_string
【发布时间】:2009-07-22 00:38:48
【问题描述】:

我希望有一个函数表现为 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

【问题讨论】:

  • +1 我正在自己编写 MySQL 类,并使用 mysql_real_escape_string() 进行参数绑定。我避免使用 mysqli,因为并非所有主机都支持它。我也避免使用多文件和多类库。我需要的只是一个整洁干净的单节课。谢谢!
  • 我也是+1。我的用例是 SugarCRM APi,我需要通过 API 将 SQL 片段推送到远程 SugarCRM 实例。虽然很讨厌,但这是我必须使用的(去敲一些 SugarCRM 开发人员)。我需要在使用 API 且与 SugarCRM 实例背后的数据库完全分离的应用程序中转义 SQL 中的字符串。

标签: php mysql mysql-real-escape-string


【解决方案1】:

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

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

【讨论】:

  • +1 感谢您的来信。我不太清楚如何使用多字节字符测试 SQL 注入攻击。
  • 我得到了一些旧代码来更新。它在没有连接的情况下使用mysql_escape_string(仍在试图找出原因)。由于该功能已被弃用,我只是想知道如何替换它。在不打开连接的情况下,可以在任何替换它的函数中指定“适当的字符集”,这当然是合理的。
  • 不可能? mysql_real_escape_string 从数据库连接中得到什么不是可以手动传递给等效函数的配置数据?编辑:请阅读下文,它在 MySQL 中调用了一个库函数,因此在 PHP 之外发生了一些处理。它可能仍然是可移植的,但保持最新状态本身就是一个项目。
  • 如果DB字符集提前知道怎么办?
  • 是的,如果你知道字符集,是什么阻止了在没有连接的情况下进行转义?
【解决方案2】:

好吧,根据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);
}

【讨论】:

  • 谢谢。我建议别的: function escape($aQuery) { return strtr($aQuery, array( "\x00" => '\x00', "\n" => '\n', "\r" => '\r', '\\' => '\\\\', "'" => "\'", '"' => '\"', "\x1a" => '\x1a' )) ; }
  • 为什么 \x1a 被替换为 \\\x1a 而不是 \\x1a?这是笔误吗?
  • -1 这非常危险。如果数据库连接使用多字节字符集,像这样简单的按字节替换可能会导致数据损坏(包括转义/引用字符)——恶意攻击者可以故意利用这一点注入任意 SQL。
  • 如果您在这方面弄错了字符集,可能会很危险。对于多字节字符集,如果 mysql 正在使用该字符集,则只需输入一个字节即可取消 \\.多字节字符集通常可以将任何内容作为第二个字节,包括 \\ for mysql 不会将其视为独立的 \\ 而是多字节字符的一部分。我不知道 UTF8 会发生什么。我希望使用 [0xB0, '\\'] 在遇到无效字节 \\ 时会停止并以该字节重新开始而不是吞下它。
  • 如果我知道字符集是 utf8,那么使用 mb_strpos()(和 mb_substr() 创建类似于 substr_replace() 的行为)来执行此操作是否安全?
【解决方案3】:

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

// 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;
}

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

【讨论】:

  • +1 感谢您的额外努力。我四处寻找更多关于多字节相关 SQL 注入的信息。
  • 我猜应该是 $return .= '\x' 。十进制($ord);而是
  • 一般来说,即使在单引号字符串中,我也更喜欢使用 '\\',因为如果你不小心,单个 '\' 会影响下一个字符。我可能又是强迫症了。
  • 该函数不遵循mysql转义规则,会导致数据完整性丢失。 “MySQL 识别表 9.1,“特殊字符转义序列”中显示的转义序列。对于所有其他转义序列,反斜杠被忽略。也就是说,转义字符被解释为好像没有转义。例如,“\x”只是“x”。” - dev.mysql.com/doc/refman/5.6/en/…
  • \xAA 实际上是否意味着 MySQL 字符串文字中的文本“xAA”?文档似乎说 \x 没有任何特殊含义,因此 \ 将被忽略。 dev.mysql.com/doc/refman/5.0/en/string-literals.html
【解决方案4】:

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

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

安全修复:

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

作为 OSDB 联盟项目间安全协作的一部分,Josh Berkus 和 Tom Lane 发现并报告了此漏洞。更多关于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_ESCAPE 启用 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。

【讨论】:

猜你喜欢
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
  • 2012-07-11
  • 2015-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-27
相关资源
最近更新 更多