【问题标题】:PHP SQL statement escapingPHP SQL 语句转义
【发布时间】:2011-09-02 22:03:45
【问题描述】:

我想使用以下语句向每个用户显示他们调用的位置:

$result = mysql_query("SELECT `CallerNumber`, `CalleeNumber`, `ServiceCost` FROM `calls` WHERE `Customer_ID` = $current_user['CustomerID']");

$current_user['CustomerID'] 部分导致错误。我试图用 / 转义将它放在单引号内,但它没有用。如何做到这一点?

【问题讨论】:

    标签: php mysql sql escaping


    【解决方案1】:

    自从我做 PHP 以来已经有一段时间了,但我认为你需要的是这个:

    $result = mysql_query("SELECT `CallerNumber`, `CalleeNumber`, `ServiceCost` FROM `calls` WHERE `Customer_ID` = '" . mysql_real_escape_string($current_user['CustomerID']) . "'");
    

    (我刚刚查了mysql_real_escape_string,如果不是常用的,请见谅。)

    另外,转义是使用反斜杠 (\) 而不是正斜杠 (/) 完成的

    【讨论】:

    • -1,但几乎,您需要始终用单引号将注入的值括起来,否则 mysql_real_escape_string() 将无能为力。
    • @Johan 好的,感谢您指出这一点,我已经解决了(我认为)
    【解决方案2】:

    你可以在下面试试这个。

    $arg = $current_user['CustomerID'];
    $result = mysql_query("SELECT `CallerNumber`, `CalleeNumber`, `ServiceCost` FROM `calls` WHERE `Customer_ID` = '$arg'");
    

    【讨论】:

    • -1,失败。如果$arg 是字符串,则空格会破坏此代码。如果$current_user['customerID'] 可以被用户操纵,那么您就有了 SQL 注入。非常糟糕的代码。
    • @Johan .. 你是对的,但我的目标是解决错误并让代码首先工作。我不想开始宣扬安全和最佳实践。 :)
    • @scartag,不解决这个问题的答案比无用更糟糕,它很危险。 #1 安全威胁(OK #2,参见:blogs.oracle.com/carolmcdonald/entry/owasp_top_10_number_2)这是 #1/#2,它多年来一直在变化。
    【解决方案3】:

    唯一正确的答案是:

    如果不是程序自己生成的,请先转义参数。
    永远是个好主意!将要注入到查询中的转义变量。
    使用 PDO 是一个更好的主意,但这是另一个主题。

    $arg = mysql_real_escape_string($current_user['CustomerID']);
    

    然后将注入的变量用单引号括起来否则转义将不起作用!

    $query = "SELECT CallerNumber, CalleeNumber, ServiceCost 
              FROM calls WHERE Customer_ID = '$arg' ");
    

    如果$var 包含空格或其他特殊变量,这也将防止您的 SQL 语句中出现语法错误。

    不需要在列名周围使用反引号,除非您使用保留字作为列名, 或者您在列/表名中使用空格或其他奇怪字符

    【讨论】:

    • 哦,好的。该参数由程序、数据库生成,我正在获取它。如果我从用户那里得到它,我会逃避它。谢谢
    • @Cimborn,我很困惑,你问escaping 但是当我回答转义部分时,你不想知道转义。无论如何,我的观点是,如果你不使用 PDO,你应该总是逃避,因为事情会发生变化,并且来自程序内部的数据现在可能会在明天看到数据来自用户的代码重构。此外,用户可以访问比许多程序员意识到的更多的数据。
    • @Cimbom,我知道你没有投反对票,因为只有 1 个代表这是不可能的。当您对他们投反对票并报复他们时,有些人会感到不安,这没什么大不了的,但有时很高兴知道真正的投反对票者必须将您的问题标记为无用的原因是什么。我对 SO 的一些最有启发性的时刻是由于反对票的解释而产生的。不说明原因就投反对票是愚蠢的,因为没有机会学习。
    • @Johan 老实说,我认为你值得一票。您的答案显然是这里最好的答案。来自我的 +1 :)
    • 只有那些通过注射攻击网站的人会否决它:D 所以,是的。
    【解决方案4】:

    对于双引号或 heredocs (EOT) 中的变量(包括数组甚至来自对象的属性调用),只需将它们括在大括号中即可。

    $result = mysql_query("SELECT `CallerNumber`, `CalleeNumber`, `ServiceCost` FROM `calls` WHERE `Customer_ID` = {$current_user['CustomerID']}");
    

    【讨论】:

    • @Johan 我正在根据他的问题来回答他的问题。但我同意你的观点,即在不清理的情况下构建 SQL 字符串是一种不好的做法,因为它容易发生 SQL 注入。虽然考虑到他的问题的上下文,但不知道 $current_user 来自哪里,因此我们不能断定代码是错误的。
    • 当 $current_user.... 包含空格时,{} 将不起作用,请参阅 codepad.org/cM9V2YX4 了解为什么它不起作用
    • @Johan 感谢您的评论!这仅在 {$current_user['CustomerID']} 是数字时才有效。如果你期望一个带或不带空格的字符串,这会给你一个错误。
    【解决方案5】:

    您可以使用{$current_user['CustomerID']} 代替$current_user['CustomerID']

    仅在$current_user['CustomerID'] 不是用户输入的情况下使用,否则应使用mysql_real_escape_string() 以避免SQL Injection

    【讨论】:

    • 现在我正在使用这个答案。这也容易发生 SQL 注入吗?
    • {} 不像您认为的那样工作 mysql_real_escape_string() 您需要改用单引号。这会让你大开眼界。
    • 查看codepad.org/cM9V2YX4 的演示,了解如果$current_user['CustomerID'] 中有空格,这将如何失败。
    猜你喜欢
    • 1970-01-01
    • 2014-03-01
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    相关资源
    最近更新 更多