FILTER_SANITIZE_EMAIL是否足够或者还需要mysql_real_escape_string来避免PHP / MySQL中的安全问题?

时间:2015-05-25 18:01:54

标签: php mysql security sql-injection

我正在检查对这样的数据库的输入:

myForm1.Refresh();

然后:

$email = $_POST['newsletter_email'];
$email = filter_var($email, FILTER_SANITIZE_EMAIL); 

问题是,它足够好吗?或者我也应该使用$is_user = $db->count_rows('users', "WHERE email='" . $email . "'");

2 个答案:

答案 0 :(得分:3)

这个问题分为两部分。

  1. 如何验证电子邮件地址。
  2. How to prevent SQL Injection
  3. 输入验证

    $email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
    if ($email !== false) {
        // Well, you've got yourself a valid email address!
    }
    

    防止SQL注入

    请勿使用mysql_real_escape_string()prevent SQL Injection的正确方法是使用参数化查询。也称为准备陈述。

    推荐阅读:

    您的代码应如下所示:

    $stmt = $db->prepare('SELECT count(userid) FROM users WHERE email = ?');
    if ($stmt->exec([ $email ])) {
        $is_user = $stmt->fetchColumn(0);
    }
    

    如果这对您来说太麻烦,您可以加载EasyDB库并使查询看起来像这样:

    $is_user = $db->cell('SELECT count(userid) FROM users WHERE email = ?', $email);
    

    请停止使用输入转义并采用预备语句。他们将查询和参数发送到不同的数据包中,这意味着即使使用Unicode黑客攻击也无法改变查询结构。

    重要

    您必须正确使用预准备语句(即永远不要将用户输入与传递给prepare()的查询字符串连接起来)以实现这种保证的安全级别。

    此外,在PHP中,某些驱动程序默认模拟准备好的语句。来自PHP manual

      

    PDO :: ATTR_EMULATE_PREPARES启用或禁用预准备语句的模拟。某些驱动程序不支持本机预处理语句或对它们的支持有限。使用此设置可强制PDO始终模拟预准备语句(如果TRUE),或尝试使用本机预准备语句(如果FALSE)。如果驱动程序无法成功准备当前查询,它将始终回退到模拟预准备语句。需要布尔。

    模拟预处理语句不提供与真实预处理语句相同的安全保证(即data/instruction separation)。为安全起见,请禁用模拟准备。

    $db = new PDO(/* etc */);
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    

答案 1 :(得分:0)

你正在"消毒"而不是"验证"输入。仅仅因为您使用FILTER_SANITIZE_EMAIL,并不意味着输入是电子邮件地址。所以是的,在你的例子中mysql_real_escape_string()将是一个明智的选择。

<?php

$email = filter_var($_POST['newsletter_email'], FILTER_SANITIZE_EMAIL);

// Validate the post data as an email address.
IF (filter_var($email, FILTER_VALIDATE_EMAIL)) {
  $cln_email = mysql_real_escape_string($email);
  $is_user = $db->count_rows('users', "WHERE email='" . $cln_email. "'");
}
?>