mysql_real_escape_string是否容易受到无效的UTF-8攻击,例如过长的UTF-8或生成错误的UTF-8序列?

时间:2014-01-13 12:40:51

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

假设我的数据库设置如下,使用utf-8(mysql中的完整4mb版本)

mysql_query("SET CHARACTER SET utf8mb4");
mysql_query("SET NAMES utf8mb4");

我在将字符串放入sql之前使用mysql_real_escape_string来逃避不需要的字符(注意 - 我不是在寻找切换到PDO的建议,我想确定mysql_real_escape_string是否可以安全地防止超长的utf8等)。

$input = mysql_real_escape_string($_POST['field']);
$sql = "SELECT * FROM `table` WHERE `header`='$input'";

我需要对$ _POST ['field'进行任何验证(例如检查字符串是否有效UTF-8并且不会过长并且不包含无效序列等) mysql_real_escape_string还是足够的?

2 个答案:

答案 0 :(得分:2)

在我回答之前发布公共服务公告。你还在使用mysql_query。即使你不想去PDO,你最终也必须升级到mysqli。所有mysql_函数都已折旧(请参阅上一个链接中的大红色可怕框),并且可能会在PHP 5.6中删除。这很重要,因为在您的案例中建议PDO的主要原因是prepared statementsmysqli也可以这样做。准备好的语句远比攻击更容易受到注入攻击,但需要更多查询(性能影响小)。

至于UTF8,我建议使用mb_check_encoding来确保字符串在尝试插入之前至少是有效的UTF8。

最后,有this answer,它提供了这些智慧的话语

  

另一种让自己进入热水的方法   mysql_real_escape_string是您设置数据库连接时   使用错误的方法编码。你应该这样做:

     

mysql_set_charset('utf8',$ link);

     

你也可以这样做:

     

mysql_query(“SET NAMES'utf8'”,$ link);

     

问题是后者绕过了mysql_ API,但仍然如此   认为你正在使用latin1(或其他东西)与数据库交谈   其他)。现在使用mysql_real_escape_string时,它会假设   错误的字符编码和转义字符串不同于   数据库稍后会解释它们。通过运行SET NAMES查询,   你已经在mysql_客户端API如何处理之间创建了一个裂缝   字符串以及数据库如何解释这些字符串。这可以   用于某些多字节字符串情况下的注入攻击。

答案 1 :(得分:1)

所有输入验证和反SQL注入都受到 soo许多错误概念的影响。事实上,所有这些归结为一件事:

确保正确的SQL查询语法

如果您能够确保任何输入数据的SQL语法正确,那么您是安全的,并且您根本不需要阅读或研究有关验证或SQL注入的任何内容。因为所有这些漏洞只有在允许不正确的SQL语法的情况下才有可能。

为了确保您的SQL查询语法正确,您必须确保$input以正确的方式转义。查看PHP文档:http://php.net/mysql_real_escape_string

  

警告安全:默认字符集

     

字符集必须在服务器级别设置,或者使用   API函数mysql_set_charset()对它有影响   mysql_real_escape_string()。请参阅有关字符集的概念部分   了解更多信息。

因此,必须在您的字符集上正确通知mysql_real_escape_string才能正常转义。因此,您应该执行以下操作:

,而不是mysql_query("SET NAMES utf8mb4");
mysql_set_charset("utf8mb4");