我在这里看到一些人指出,使用mysql_real_escape_string串联查询不会(完全)保护您免受SQL注入(inject)攻击。

但是,我还没有看到一个输入示例,该示例说明了mysql_real_escape_string不能保护您免受攻击的攻击。大多数示例都忘记了mysql_query仅限于一个查询,并且错误地使用了mysql_real_escape_string

我能想到的唯一示例如下:

mysql_query('DELETE FROM users WHERE user_id = '.mysql_real_escape_string($input));

这不会保护您免受以下输入的影响:
5 OR 1=1

我认为这是对mysql_real_escape_string的不正确使用,而不是缺点,它是为字符串而非数字值设计的。您应该强制转换为数字类型,或者如果要在 sanitizer 时将输入视为字符串,则应在查询中执行相同的操作,并在其两边使用引号引起来。

谁能提供一个输入示例,它可以绕过mysql_real_escape_string而不依赖于对数值的不正确处理,或者忘记mysql_query只能执行一个查询?

编辑:我对mysql_real_escape_string的局限性感兴趣,并且没有将其与替代项进行比较,我意识到新项目有更好的选择,并且对此没有争议。

最佳答案

mysql_real_escape_string或mysql_扩展名的主要缺点是,与其他更现代的API(尤其是预准备的语句)相比,很难正确地应用它。 mysql_real_escape_string应该仅在一种情况下使用:转义用作引号之间SQL语句中的值的文本内容。例如。:

$value = mysql_real_escape_string($value, $link);
$sql = "... `foo` = '$value' ...";
                     ^^^^^^
mysql_real_escape_string确保上述上下文中的$value不会弄乱SQL语法。它不起作用,您可能会在这里想到:
$sql = "... `foo` = $value ...";

或在这里:
$sql = "... `$value` ...";

或在这里:
$sql = mysql_real_escape_string("... `foo` = '$value' ...");

如果将其应用于在除SQL语句中带引号的字符串之外的任何上下文中使用的值,则该值将被错误地使用,并且可能会或可能不会弄乱所得的语法和/或允许某些人提交可能启用SQL注入(inject)攻击的值。 mysql_real_escape_string的用例非常狭窄,但是很少能正确理解。

使用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如何处理字符串与数据库如何解释这些字符串之间创建了一条裂痕。这可以用于某些多字节字符串情况下的注入(inject)攻击。

如果正确应用,我知道mysql_real_escape_string中没有基本的注入(inject)漏洞。 但是,主要的问题是,错误地应用它非常容易,这会带来漏洞。

关于php - mysql_real_escape_string的缺点?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12703420/

10-09 03:46