【问题标题】:Is my PDO query safe from SQL injection [duplicate]我的 PDO 查询对 SQL 注入安全吗?
【发布时间】:2013-03-07 02:20:58
【问题描述】:

我对 PDO 还很陌生,想知道下面的查询是否可以避免 SQL 注入。如果是这样,我将在整个网站上使用此方法。

    // make connection to DB
$db = new PDO('mysql:host='.$dateBaseHost.';dbname='.$dateBaseName, $dateBaseUsername, $dateBasePassword);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


//simple query and binding with results
$query = $db->prepare(" SELECT * FROM `profile` WHERE `fullname` = :fullname ");

$search = (isset($_GET['search']) === true) ? $_GET['search'] : '' ; // ? : shorthand for if else

// bind parameters - avoids SQL injection
$query->bindValue(':fullname', $search);

//try... if not catch exception
try {
    // run the query
    $query->execute();

    $rows = $query->fetchAll(PDO::FETCH_ASSOC);
    echo '<pre>', print_r($rows, true),'</pre>';
}
catch (PDOException $e){
    sendErrorMail($e->getMessage(), $e->getFile(), $e->getLine());
}

【问题讨论】:

  • 只要你使用参数化,查询你的查询是安全的。
  • 是的。您正在使用参数化,它将自动进行必要的转义。好东西!

标签: php sql pdo sql-injection


【解决方案1】:

是的 - 以这种方式使用时,参数化查询不会被注入。

【讨论】:

  • 它只是安全地抵御基本攻击......
【解决方案2】:

只要您正确使用准备好的语句,您就不会被注入。但是只要您直接将任何外部数据插入到查询中,即使它是准备好的语句,例如

INSERT INTO $table VALUES (:param)

您很容易受到攻击 - 在这种情况下,$table 可能会被破坏,即使您使用的是准备好的语句。

任何告诉你简单地切换 mysql->PDO 或 mysqli 会让你更安全的人是彻头彻尾的错误。使用任一库,您都可能同样容易受到注入攻击。

【讨论】:

    【解决方案3】:

    是的,它相当安全,但整个脚本可以改进:

    if (isset($_GET['search']) {
        // make connection to DB
        $opt = array(
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        );
        $dsn = "mysql:host=$dateBaseHost;dbname=$dateBaseName;charset=$dateBaseCharset";
        $db  = new PDO($dsn, $dateBaseUsername, $dateBasePassword, $opt);
    
        //simple query and binding with results
        $query = $db->prepare("SELECT * FROM profile WHERE fullname = ?");
        $query->execute(array($_GET['search']));
        $rows = $query->fetchAll();
        echo '<pre>', print_r($rows, true),'</pre>';
    }
    
    • 您需要将 errmode 设置为连接选项
    • 从不使用 try..catch 处理错误消息。如果您想针对每个错误发送电子邮件(这太疯狂了),您必须为此设置my_exception handler()
    • 将搜索设置为空字符串没有任何意义
    • 应将连接到 PDO 的连接移至单独的文件(未显示)
    • 字符集必须在 DSN 中设置

    【讨论】:

    • 为什么您应该从不使用try...catch 块来处理错误?他们在所有文档中都有它..?
    • 我不是说“错误”而是“错误信息”。是的,他们都错了
    • 我想知道您对 Marc B 的答案和解决方案的看法。
    【解决方案4】:

    你也应该

    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    

    默认情况下,它使用模拟模式,它只是做mysql_real_escape_string 所做的事情。在某些边缘情况下,您仍然容易受到 SQL 注入的攻击。

    【讨论】:

    • @YourCommonSense:但仍然很重要,请参阅骗子的答案,尤其是this one
    • 这实际上是做什么的?
    • @user2183216:这已经在我的回答中了,它关闭了模拟模式。在模拟模式下,PDO 只是在变量周围加上引号并转义所有单引号,但这可能还不够。另请阅读重复的问题。
    猜你喜欢
    • 1970-01-01
    • 2010-10-12
    • 2012-05-20
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    相关资源
    最近更新 更多