逃避一个字符串是什么意思?

时间:2012-05-18 02:57:07

标签: php mysql security escaping

我正在阅读Does $_SESSION['username'] need to be escaped before getting into an SQL query?并且它说“你需要转义你传递给sql查询的每个字符串,无论其来源如何”。现在我知道这样的事情是非常基本的。谷歌搜索结果超过20,000。 Stackoverflow本身只有20页的结果,但没有人真正解释什么是字符串转义或如何做。这只是假设。你能帮助我吗?我想学习,因为我一直在用PHP制作一个Web应用程序。

我看过: Inserting Escape CharactersWhat are all the escape characters in Java?Cant escape a string with addcslashes()Escape characterwhat does mysql_real_escape_string() really do?How can i escape double quotes from a string in php?MySQL_real_escape_string not adding slashes?remove escape sequences from string in php我可以继续,但我相信你明白了。这不是懒惰。

3 个答案:

答案 0 :(得分:117)

转义字符串意味着减少该字符串中使用的引号(和其他字符)的歧义。例如,当您定义字符串时,通常用双引号或单引号括起来:

"Hello World."

但是如果我的字符串中有双引号怎么办?

"Hello "World.""

现在我有歧义 - 翻译不知道我的字符串在哪里结束。如果我想保留双引号,我有几个选择。我可以在我的字符串周围使用单引号:

'Hello "World."'

或者我可以逃避我的报价:

"Hello \"World.\""

以斜杠开头的任何引号都是转义,并且被理解为字符串值的一部分。

在查询方面,MySQL有一些它所关注的关键字,我们不能在查询中使用这些关键字而不会造成一些混淆。假设我们有一个值表,其中一列被命名为“Select”,我们想要选择:

SELECT select FROM myTable

我们现在在查询中引入了一些含糊之处。在我们的查询中,我们可以通过使用反向标记来减少这种模糊性:

SELECT `select` FROM myTable

这消除了我们在选择字段名称时使用不良判断所引入的混淆。

只需将您的值传递给mysql_real_escape_string(),即可为您处理很多问题。在下面的示例中,您可以看到我们通过此函数传递用户提交的数据,以确保它不会对我们的查询造成任何问题:

// Query
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
            mysql_real_escape_string($user),
            mysql_real_escape_string($password));

存在用于转义字符串的其他方法,例如add_slashesaddcslashesquotemeta等,但您会发现当目标是运行安全查询时,大型开发人员更喜欢mysql_real_escape_stringpg_escape_string(在PostgreSQL的上下文中。

答案 1 :(得分:19)

某些字符对您正在使用的SQL数据库有特殊意义。在查询中使用这些字符时,它们可能会导致意外和/或意外行为,包括允许攻击者危害您的数据库。为了防止这些字符以这种方式影响查询,需要对其进行转义,或者以不同的方式说明,需要告知数据库不要将它们视为此查询中的特殊字符。

如果是mysql_real_escape_string(),它会逃脱\x00\n\r\'"\x1a因为这些,如果没有转义,可能会导致前面提到的问题,其中包括使用MySQL数据库进行SQL注入。

答案 2 :(得分:1)

为简单起见,您基本上可以想象反斜杠“ \”是运行时传递给解释器的命令。

例如在解释此语句时:

$txt = "Hello world!";

在词法分析阶段(或将语句拆分为单独的标记时),这些将是已识别的标记 $txt="Hello world!";

但是,字符串中的反斜杠将导致额​​外的标记集,并被解释为使用紧随其后的字符进行操作的命令: 例如

$txt = "this \" is escaped";

产生以下令牌: $txt="this\"is escaped,{{ 1}}和"

解释器已经基于;令牌后的字符知道(或具有它可以采用的预设路线)该做什么。因此,对于\,它将继续将其视为字符而不是字符串结尾命令。