我一直在使用mysql_real_escape_string和其他函数清理我的输入,并且最近读到Prepared Statements是真正安全的唯一方法。但是我不愿意使用它们有两个原因:我不想重写代码,我读到使用它们会对性能产生影响(查询在这个应用程序中被广泛使用)。
所以我正在寻找一个最近的,一个具体的例子,其中mysql_real_escape_string在查询中失败,解决方法是使用Prepared Statements(即没有办法进一步消毒输入并保证它是安全的)。
我问这个是因为我能找到符合上述标准的唯一例子是从前一段时间开始,并且已经在更新版本的php中修补了。
答案 0 :(得分:7)
从函数的PHP文档(http://php.net/mysql_real_escape_string)中,它说“mysql_real_escape_string()调用MySQL的库函数mysql_real_escape_string,它将反斜杠添加到以下字符:\ x00,\ n,\ r,\,' ,“和\ x1a。” 因此,它的用处取决于上下文。因此,例如,如果您有以下情况:
$user_input = mysql_real_escape_string($_GET['user_input']);
$query = "SELECT * FROM `users` WHERE `id` = $user_input";
$result = mysql_query($query);
嗯,那太愚蠢了。因为如果字符串是0 or 9=9
,那么它不包含函数转义的任何字符。但是,当注入$ query文字时,它会生成:
$query = "SELECT * FROM `users` WHERE `id` = 0 or 9=9";
这将返回users
表中的所有行......这可能不是程序员的意图。
因此,如果用户输入由mysql_real_escape_string()处理但是在整数或其他数字数据类型的上下文中使用,那么它将无法提供足够的保护。
使用预准备语句,您可以确保每个值不仅被转义,而且被验证为正确的数据类型。
在上面的例子中,最安全的处理方法是使用intval()函数而不是mysql_real_escape_string()函数。
希望这是有道理的。
答案 1 :(得分:1)
mysql_real_escape_string()
的全部目的是100%保证您使用它逃脱的数据中不会出现SQL注入。它远远优于addslashes()
,因为它考虑了当前连接的字符编码。
如果此功能的实际实施中没有严重错误,那么可以安全使用。
人们不希望您使用它的原因是您可能会在某个地方忘记,从而打开安全漏洞。准备好的语句更难搞砸,但如果你正确地逃避数据,构建自己的SQL没有任何根本的错误。
修改强>
请注意在建立连接后更改连接字符集的潜在能力,因此与mysql_real_escape_string
不同步。我还没有证实情况仍然存在。
另请注意,mysql_real_escape_string()
必须是在将数据与SQL连接之前对数据执行的最后一个操作。
另外,不要忘记引号!例如。 AND name = "' . mysql_real_escape_string($name) . '"
答案 2 :(得分:0)
mysql_real_escape_string 100%可靠。这就是你在失败后的转发数据中所做的事情。
e.g。
$safe = mysql_real_escape_string('some nasty injection-riddled data here');
$unsafe = htmlspecialchars($safe);
m_r_e_s将完美地完成其工作,然后你可能通过以后再次摆弄字符串来撤消所有内容。
m_r_e_s应该是在SQL查询中使用之前对字符串执行的最后一次操作。