无需连接数据库即可替代mysql_real_escape_string


91

我想拥有一个不连接数据库就表现为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
+1我自己编写MySQL类,并使用mysql_real_escape_string()进行参数绑定。我避免使用mysqli,因为并非所有托管都支持它。我也避免使用多文件和多类库。我需要的只是一个干净整洁的单一类。谢谢!
越南

我也+1。我的用例是SugarCRM APi,我需要在其中通过API将SQL片段推送到远程SugarCRM实例。尽管那是令人讨厌的,但这是我必须使用的(一起敲打一些SugarCRM开发人员的负责人)。我需要在使用API​​的应用程序中的SQL中转义字符串,该字符串与SugarCRM实例背后的数据库完全分开。
杰森

Answers:


75

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

如果仅测试,那么您可能还可以使用mysql_escape_string(),它不能100%保证不会受到SQL注入攻击,但是如果没有数据库连接就无法构建更安全的东西。


1
+1感谢您的来信。我不太确定如何使用多字节字符测试SQL注入攻击。
越南

2
我得到了一些旧代码来更新。它使用mysql_escape_string没有连接(仍然试图找出原因)。由于该功能已被弃用,我只是想知道如何替换它。可以在不用打开连接的任何函数替换中指定“适当的字符集”,这显然是合理的。
JohnK

3
不可能?mysql_real_escape_string从不是可以手动传递给等效函数的配置数据的数据库连接中得到什么?编辑:下面刚刚读到,它在MySQL中调用了一个库函数,因此在PHP之外发生了一些处理。它可能仍然是可移植的,但是使其保持最新状态本身就是一个项目。
杰森

2
如果提前知道DB字符集怎么办?
jchook

7
是的,如果您知道字符集,是什么阻止了在没有连接的情况下进行转义?
约翰

66

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

6
谢谢。我建议使用其他方法:function escape($ aQuery){return strtr($ aQuery,array(“ \ x00” =>'\ x00',“ \ n” =>'\ n',“ \ r” => '\ r','\\'=>'\\\\',“'” =>“ \'”,'“'=>'\”',“ \ x1a” =>'\ x1a')) ; }
越南

1
为什么将\ x1a替换为\\\ x1a而不是\\ x1a?这是错字吗?
Michael Z 2010年

16
-1这是非常危险的。如果数据库连接使用的是多字节字符集,则像这样的简单按字节替换可能会导致数据损坏(包括转义/引号字符)—恶意攻击者可能会故意利用这一点注入任意SQL。
eggyal 2014年

如果您弄错了字符集,可能会很危险。对于多字节字符集,如果mysql正在使用,则有人可以只输入一个字节来取消\\。多字节字符集通常可以采用任何形式,因为第二个字节包括\\(对于mysql)不会将其视为独立的\\,而是多字节字符的一部分。我不知道UTF8会发生什么。我希望通过[0xB0,'\\']击中一个无效字节\\时,该字节将停止并再次从该字节开始而不是吞下它。
jgmjgm

1
如果我知道字符集是utf8,使用它mb_strpos()(并mb_substr()创建类似于的行为substr_replace())这样做安全吗?
SOFe

28

与我的其他答案完全相反,即使使用多字节字符,此后续功能也可能是安全的。

// 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'。dechex($ ord); 相反
越南,

1
通常,我更喜欢在单引号中使用'\\',因为如果您不小心,单个'\'可能会影响下一个字符。我可能只是再次成为强迫症。
太多的PHP

1
此函数不遵循mysql的转义规则,并且会导致数据完整性丢失。“ MySQL识别出表9.1“特殊字符转义序列”中所示的转义序列。对于所有其他转义序列,将忽略反斜杠。也就是说,将转义字符解释为未转义。例如,“ \ x”只是“ x”。” - dev.mysql.com/doc/refman/5.6/en/...
velcrow

2
\ xAA实际上除了MySQL字符串文字中的文本“ xAA”以外还意味着什么吗?文档似乎说\ x没有任何特殊含义,因此\将被忽略。dev.mysql.com/doc/refman/5.0/en/string-literals.html
Jason

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中的addslashes())时,可以绕过某些多字节字符集(例如,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-mode = NO_BACKSLASH_ESCAPES或通过在服务器选项文件中设置sql-mode = NO_BACKSLASH_ESCAPES(例如,my.cnf或my.ini),也可以在服务器启动时自动启用此SQL模式。 ,具体取决于您的系统)。(缺陷号8378,CVE-2006-2753)

另请参见Bug#8303。


1
该问题已在很久以前解决。
您的常识2013年

2
还应注意NO_BACKSLASH_ESCAPES 引入其他漏洞
eggyal 2014年

2
在5.1.11中已修复-链接已断开,这里是存档:web.archive.org/web/20120501203047/http
堡垒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.